解决因spring security导致的无法跨域问题
| | |
| | | @Min(value = 1, message = "最小页数1") |
| | | private int current = 1; |
| | | |
| | | @ApiModelProperty(value = "条数",example = "1~100") |
| | | @ApiModelProperty(value = "条数",example = "1") |
| | | @Min(value = 1, message = "最小条数1") |
| | | @Max(value = 100, message = "最大条数100") |
| | | private int pageSize = 20; |
New file |
| | |
| | | package com.ycl.config; |
| | | |
| | | import org.springframework.context.annotation.Configuration; |
| | | import org.springframework.security.config.annotation.web.builders.HttpSecurity; |
| | | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; |
| | | import org.springframework.web.cors.CorsConfiguration; |
| | | import org.springframework.web.cors.CorsConfigurationSource; |
| | | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; |
| | | |
| | | import javax.servlet.*; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | import java.util.Arrays; |
| | | import java.util.Collections; |
| | | |
| | | /** |
| | | * @author Lyq |
| | | * @version 1.0 |
| | | * @date 2022/9/10 1:04 |
| | | */ |
| | | public class WebSecurityCorsFilter implements Filter { |
| | | @Override |
| | | public void init(FilterConfig filterConfig) throws ServletException { |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { |
| | | HttpServletResponse res = (HttpServletResponse) response; |
| | | res.setHeader("Access-Control-Allow-Origin", "*"); |
| | | res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT"); |
| | | res.setHeader("Access-Control-Max-Age", "3600"); |
| | | res.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept, x-requested-with, Cache-Control, os, version, source"); |
| | | chain.doFilter(request, res); |
| | | } |
| | | |
| | | @Override |
| | | public void destroy() { |
| | | |
| | | } |
| | | } |
| | |
| | | * @param userDetails 从数据库中查询出来的用户信息 |
| | | */ |
| | | public boolean validateToken(String token, UserDetails userDetails) { |
| | | String username = getUserNameFromToken(token); |
| | | String username = parseToken(token).getUsername(); |
| | | return username.equals(userDetails.getUsername()) && !isTokenExpired(token); |
| | | } |
| | | |
| | |
| | | import com.ycl.utils.JwtTokenUtil; |
| | | import com.ycl.utils.common.LiveTimeMillisecond; |
| | | import com.ycl.utils.common.NetworkUtil; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import javax.annotation.Resource; |
| | |
| | | @Resource |
| | | private RedisService redisService; |
| | | |
| | | @Value("${jwt.tokenHead}") |
| | | private String tokenHead; |
| | | |
| | | public void saveUser(Long userId, String token, String redisKey) { |
| | | redisService.set(redisKey.concat(userId.toString()), token, LiveTimeMillisecond.s2592000.time); |
| | |
| | | if (StrUtil.isBlank(accessToken)) { |
| | | throw new ApiException(ResultCode.NOT_LOGGED); |
| | | } |
| | | AuthInfo authInfo = jwtTokenUtil.parseToken(accessToken); |
| | | String authToken = accessToken.substring(this.tokenHead.length());// The part after "Bearer " |
| | | AuthInfo authInfo = jwtTokenUtil.parseToken(authToken); |
| | | return authInfo.getUserId(); |
| | | } |
| | | |
| | |
| | | if (StrUtil.isBlank(accessToken)) { |
| | | throw new ApiException(ResultCode.NOT_LOGGED); |
| | | } |
| | | AuthInfo authInfo = jwtTokenUtil.parseToken(accessToken); |
| | | String authToken = accessToken.substring(this.tokenHead.length());// The part after "Bearer " |
| | | AuthInfo authInfo = jwtTokenUtil.parseToken(authToken); |
| | | // AuthInfo authInfo = jwtTokenUtil.parseToken(accessToken); |
| | | return authInfo.getUsername(); |
| | | } |
| | | } |
| | |
| | | package com.ycl.component; |
| | | |
| | | import com.ycl.entity.auth.AuthInfo; |
| | | import com.ycl.utils.JwtTokenUtil; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | import java.util.Enumeration; |
| | | |
| | | /** |
| | | * JWT登录授权过滤器 |
| | |
| | | protected void doFilterInternal(HttpServletRequest request, |
| | | HttpServletResponse response, |
| | | FilterChain chain) throws ServletException, IOException { |
| | | System.out.println(request); |
| | | // Enumeration<String> headerNames = request.getHeaderNames(); |
| | | // while (headerNames.hasMoreElements()){ |
| | | // System.out.println(headerNames.nextElement()); |
| | | // } |
| | | String authHeader = request.getHeader(this.tokenHeader); |
| | | if (authHeader != null && authHeader.startsWith(this.tokenHead)) { |
| | | String authToken = authHeader.substring(this.tokenHead.length());// The part after "Bearer " |
| | | String username = jwtTokenUtil.getUserNameFromToken(authToken); |
| | | AuthInfo authInfo = jwtTokenUtil.parseToken(authToken); |
| | | String username = authInfo.getUsername(); |
| | | LOGGER.info("checking username:{}", username); |
| | | if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { |
| | | UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); |
| | | UserDetails userDetails = this.userDetailsService.loadUserByUsername(authInfo.getUsername()); |
| | | if (jwtTokenUtil.validateToken(authToken, userDetails)) { |
| | | UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); |
| | | authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); |
| | |
| | | .authenticationEntryPoint(restAuthenticationEntryPoint) |
| | | // 自定义权限拦截器JWT过滤器 |
| | | .and() |
| | | .addFilterBefore(webSecurityCorsFilter(), UsernamePasswordAuthenticationFilter.class) |
| | | .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); |
| | | //有动态权限配置时添加动态权限校验过滤器 |
| | | if(dynamicSecurityService!=null){ |
| | | if (dynamicSecurityService != null) { |
| | | registry.and().addFilterBefore(dynamicSecurityFilter, FilterSecurityInterceptor.class); |
| | | } |
| | | return httpSecurity.build(); |
| | | } |
| | | |
| | | @Bean |
| | | public WebSecurityCorsFilter webSecurityCorsFilter() { |
| | | return new WebSecurityCorsFilter(); |
| | | } |
| | | } |
| | |
| | | |
| | | jwt: |
| | | tokenHeader: Authorization #JWT存储的请求头 |
| | | secret: luozi-admin-secret #JWT加解密使用的密钥 |
| | | secret: platform-secret #JWT加解密使用的密钥 |
| | | expiration: 604800 #JWT的超期限时间(60*60*24*7) |
| | | tokenHead: 'Bearer ' #JWT负载中拿到开头 |
| | | |