diff --git a/src/main/java/com/youlai/system/framework/easycaptcha/config/EasyCaptchaConfig.java b/src/main/java/com/youlai/system/framework/easycaptcha/config/EasyCaptchaConfig.java index 04c237c2..68767de3 100644 --- a/src/main/java/com/youlai/system/framework/easycaptcha/config/EasyCaptchaConfig.java +++ b/src/main/java/com/youlai/system/framework/easycaptcha/config/EasyCaptchaConfig.java @@ -8,6 +8,8 @@ import org.springframework.context.annotation.Configuration; import java.awt.*; /** + * EasyCaptcha 配置类 + * * @author: haoxr * @date: 2023/03/24 */ diff --git a/src/main/java/com/youlai/system/framework/security/config/SecurityConfig.java b/src/main/java/com/youlai/system/framework/security/config/SecurityConfig.java index de91b1fc..f51df3b2 100644 --- a/src/main/java/com/youlai/system/framework/security/config/SecurityConfig.java +++ b/src/main/java/com/youlai/system/framework/security/config/SecurityConfig.java @@ -1,5 +1,6 @@ package com.youlai.system.framework.security.config; +import com.youlai.system.framework.security.constant.SecurityConstants; import com.youlai.system.framework.security.filter.JwtAuthenticationFilter; import com.youlai.system.framework.security.exception.MyAccessDeniedHandler; import com.youlai.system.framework.security.exception.MyAuthenticationEntryPoint; @@ -43,27 +44,27 @@ public class SecurityConfig { .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeHttpRequests() + .requestMatchers(SecurityConstants.LOGIN_PATH).permitAll() // 登录接口放行但会走过滤器链-验证码校验 .anyRequest().authenticated() .and() - .formLogin() - .loginProcessingUrl("/api/v1/auth/login").permitAll() - .and() .exceptionHandling() .authenticationEntryPoint(myAuthenticationEntryPoint) .accessDeniedHandler(myAccessDeniedHandler) ; - // disable cache - http.headers().cacheControl(); - // 验证码校验过滤器 - http.addFilterAt(new VerifyCodeFilter(),UsernamePasswordAuthenticationFilter.class); + http.addFilterBefore(new VerifyCodeFilter(),UsernamePasswordAuthenticationFilter.class); // JWT 校验过滤器 http.addFilterBefore(new JwtAuthenticationFilter(jwtTokenManager), UsernamePasswordAuthenticationFilter.class); return http.build(); } + /** + * 不走过滤器链的放行配置 + * + * @return + */ @Bean public WebSecurityCustomizer webSecurityCustomizer() { return (web) -> web.ignoring() diff --git a/src/main/java/com/youlai/system/framework/security/constant/SecurityConstants.java b/src/main/java/com/youlai/system/framework/security/constant/SecurityConstants.java new file mode 100644 index 00000000..d044b35b --- /dev/null +++ b/src/main/java/com/youlai/system/framework/security/constant/SecurityConstants.java @@ -0,0 +1,16 @@ +package com.youlai.system.framework.security.constant; + +/** + * Security 常量 + * + * @author: haoxr + * @date: 2023/03/24 + */ +public interface SecurityConstants { + + /** + * 登录接口路径 + */ + String LOGIN_PATH = "/api/v1/auth/login"; + +} diff --git a/src/main/java/com/youlai/system/framework/security/filter/JwtAuthenticationFilter.java b/src/main/java/com/youlai/system/framework/security/filter/JwtAuthenticationFilter.java index 9852ecd0..04eab886 100644 --- a/src/main/java/com/youlai/system/framework/security/filter/JwtAuthenticationFilter.java +++ b/src/main/java/com/youlai/system/framework/security/filter/JwtAuthenticationFilter.java @@ -4,6 +4,7 @@ import cn.hutool.core.util.StrUtil; import com.youlai.system.common.result.ResultCode; import com.youlai.system.common.util.ResponseUtils; import com.youlai.system.framework.security.JwtTokenManager; +import com.youlai.system.framework.security.constant.SecurityConstants; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; @@ -23,8 +24,6 @@ import java.io.IOException; */ public class JwtAuthenticationFilter extends OncePerRequestFilter { - private static final AntPathRequestMatcher DEFAULT_ANT_PATH_REQUEST_MATCHER = new AntPathRequestMatcher("/api/v1/auth/login", "POST"); - private static final String TOKEN_PREFIX = "Bearer "; private final JwtTokenManager tokenManager; @@ -35,28 +34,27 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { - if (DEFAULT_ANT_PATH_REQUEST_MATCHER.matches(request)) { - // 非登录接口放行 + if (SecurityConstants.LOGIN_PATH.equals(request.getRequestURI())) { + // 登录接口放行 chain.doFilter(request, response); - return; - } + }else{ + String jwt = resolveToken(request); + if (StrUtil.isNotBlank(jwt) && SecurityContextHolder.getContext().getAuthentication() == null) { + try { + // 验证JWT + this.tokenManager.validateToken(jwt); - String jwt = resolveToken(request); - if (StrUtil.isNotBlank(jwt) && SecurityContextHolder.getContext().getAuthentication() == null) { - try { - // 验证JWT - this.tokenManager.validateToken(jwt); + // JWT验证有效获取Authentication存入Security上下文 + Authentication authentication = this.tokenManager.getAuthentication(jwt); + SecurityContextHolder.getContext().setAuthentication(authentication); - // JWT验证有效获取Authentication存入Security上下文 - Authentication authentication = this.tokenManager.getAuthentication(jwt); - SecurityContextHolder.getContext().setAuthentication(authentication); - - chain.doFilter(request, response); - }catch (Exception e){ + chain.doFilter(request, response); + }catch (Exception e){ + ResponseUtils.writeErrMsg(response, ResultCode.TOKEN_INVALID); + } + }else{ ResponseUtils.writeErrMsg(response, ResultCode.TOKEN_INVALID); } - }else{ - ResponseUtils.writeErrMsg(response, ResultCode.TOKEN_INVALID); } } diff --git a/src/main/java/com/youlai/system/framework/security/filter/VerifyCodeFilter.java b/src/main/java/com/youlai/system/framework/security/filter/VerifyCodeFilter.java index e4434f68..0b8daafb 100644 --- a/src/main/java/com/youlai/system/framework/security/filter/VerifyCodeFilter.java +++ b/src/main/java/com/youlai/system/framework/security/filter/VerifyCodeFilter.java @@ -6,13 +6,13 @@ import cn.hutool.extra.spring.SpringUtil; import com.youlai.system.common.constant.CacheConstants; import com.youlai.system.common.result.ResultCode; import com.youlai.system.common.util.ResponseUtils; +import com.youlai.system.framework.security.constant.SecurityConstants; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.web.filter.OncePerRequestFilter; import java.io.IOException; @@ -25,10 +25,6 @@ import java.io.IOException; */ public class VerifyCodeFilter extends OncePerRequestFilter { - /** - * 拦截路径 - */ - private static final AntPathRequestMatcher DEFAULT_ANT_PATH_REQUEST_MATCHER = new AntPathRequestMatcher("/api/v1/auth/login", "POST"); public static final String VERIFY_CODE = "verifyCode"; public static final String VERIFY_CODE_KEY = "verifyCodeKey"; @@ -40,13 +36,17 @@ public class VerifyCodeFilter extends OncePerRequestFilter { @Override public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { - if (!DEFAULT_ANT_PATH_REQUEST_MATCHER.matches(request)) { - // 非登录接口放行 - chain.doFilter(request, response); - } else { + // 检验登录接口的验证码 + if (SecurityConstants.LOGIN_PATH.equals(request.getRequestURI())) { // 请求中的验证码 String requestVerifyCode = request.getParameter(VERIFY_CODE); + // TODO 兼容 2.0.0 无验证码版本,后续移除 + if (StrUtil.isBlank(requestVerifyCode)) { + // 非登录接口放行 + chain.doFilter(request, response); + return; + } // 缓存中的验证码 String verifyCodeKey = request.getParameter(VERIFY_CODE_KEY); Object cacheVerifyCode = redisTemplate.opsForValue().get(CacheConstants.VERIFY_CODE_CACHE_PREFIX + verifyCodeKey); @@ -60,6 +60,9 @@ public class VerifyCodeFilter extends OncePerRequestFilter { ResponseUtils.writeErrMsg(response, ResultCode.VERIFY_CODE_ERROR); } } + } else { + // 非登录接口放行 + chain.doFilter(request, response); } }