diff --git a/src/main/java/com/youlai/system/aspect/DuplicateSubmitAspect.java b/src/main/java/com/youlai/system/aspect/DuplicateSubmitAspect.java index ccb746a5..5a074a82 100644 --- a/src/main/java/com/youlai/system/aspect/DuplicateSubmitAspect.java +++ b/src/main/java/com/youlai/system/aspect/DuplicateSubmitAspect.java @@ -1,11 +1,10 @@ package com.youlai.system.aspect; import cn.hutool.core.util.StrUtil; -import com.youlai.system.exception.BusinessException; -import com.youlai.system.common.result.ResultCode; -import com.youlai.system.util.RequestUtils; import com.youlai.system.common.annotation.PreventDuplicateSubmit; -import com.youlai.system.security.JwtTokenManager; +import com.youlai.system.common.result.ResultCode; +import com.youlai.system.exception.BusinessException; +import com.youlai.system.security.jwt.JwtTokenProvider; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -25,7 +24,7 @@ import java.util.concurrent.TimeUnit; * 处理重复提交的切面 * * @author haoxr - * @since 3.0.0 + * @since 2.3.0 */ @Aspect @Component @@ -35,7 +34,7 @@ public class DuplicateSubmitAspect { private final RedissonClient redissonClient; - private final JwtTokenManager jwtTokenManager; + private final JwtTokenProvider jwtTokenProvider; private static final String RESUBMIT_LOCK_PREFIX = "LOCK:RESUBMIT:"; /** @@ -68,9 +67,10 @@ public class DuplicateSubmitAspect { private String generateResubmitLockKey() { String resubmitLockKey = null; HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); - String jwt = RequestUtils.resolveToken(request); - if (StrUtil.isNotBlank(jwt)) { - String jti = (String) jwtTokenManager.getTokenClaims(jwt).get("jti"); + + String token = jwtTokenProvider.resolveToken(request); + if (StrUtil.isNotBlank(token)) { + String jti = (String) jwtTokenProvider.getTokenClaims(token).get("jti"); resubmitLockKey = RESUBMIT_LOCK_PREFIX + jti + ":" + request.getMethod() + "-" + request.getRequestURI(); } return resubmitLockKey; diff --git a/src/main/java/com/youlai/system/common/annotation/DataPermission.java b/src/main/java/com/youlai/system/common/annotation/DataPermission.java index fb716d07..50789b5c 100644 --- a/src/main/java/com/youlai/system/common/annotation/DataPermission.java +++ b/src/main/java/com/youlai/system/common/annotation/DataPermission.java @@ -4,10 +4,8 @@ import java.lang.annotation.*; /** * MP数据权限注解 - *
*
* @author zc
- * @link https://gitee.com/baomidou/mybatis-plus/issues/I37I90
* @since 2.0.0
*/
@Documented
diff --git a/src/main/java/com/youlai/system/util/ExcelUtils.java b/src/main/java/com/youlai/system/common/util/ExcelUtils.java
similarity index 91%
rename from src/main/java/com/youlai/system/util/ExcelUtils.java
rename to src/main/java/com/youlai/system/common/util/ExcelUtils.java
index ae0ac6d6..aa766ea1 100644
--- a/src/main/java/com/youlai/system/util/ExcelUtils.java
+++ b/src/main/java/com/youlai/system/common/util/ExcelUtils.java
@@ -1,4 +1,4 @@
-package com.youlai.system.util;
+package com.youlai.system.common.util;
import com.alibaba.excel.EasyExcel;
import com.youlai.system.listener.easyexcel.MyAnalysisEventListener;
diff --git a/src/main/java/com/youlai/system/util/ResponseUtils.java b/src/main/java/com/youlai/system/common/util/ResponseUtils.java
similarity index 89%
rename from src/main/java/com/youlai/system/util/ResponseUtils.java
rename to src/main/java/com/youlai/system/common/util/ResponseUtils.java
index 4b6a17d3..2ed64175 100644
--- a/src/main/java/com/youlai/system/util/ResponseUtils.java
+++ b/src/main/java/com/youlai/system/common/util/ResponseUtils.java
@@ -1,6 +1,7 @@
-package com.youlai.system.util;
+package com.youlai.system.common.util;
import cn.hutool.json.JSONUtil;
+import com.youlai.system.common.result.IResultCode;
import com.youlai.system.common.result.Result;
import com.youlai.system.common.result.ResultCode;
@@ -10,6 +11,8 @@ import org.springframework.http.MediaType;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
+import static com.youlai.system.common.result.ResultCode.*;
+
/**
* 响应工具类
*
diff --git a/src/main/java/com/youlai/system/util/SecurityUtils.java b/src/main/java/com/youlai/system/common/util/SecurityUtils.java
similarity index 99%
rename from src/main/java/com/youlai/system/util/SecurityUtils.java
rename to src/main/java/com/youlai/system/common/util/SecurityUtils.java
index 2234f358..99d114f8 100644
--- a/src/main/java/com/youlai/system/util/SecurityUtils.java
+++ b/src/main/java/com/youlai/system/common/util/SecurityUtils.java
@@ -1,4 +1,4 @@
-package com.youlai.system.util;
+package com.youlai.system.common.util;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
diff --git a/src/main/java/com/youlai/system/config/SecurityConfig.java b/src/main/java/com/youlai/system/config/SecurityConfig.java
index 89dfe2a7..1328e24f 100644
--- a/src/main/java/com/youlai/system/config/SecurityConfig.java
+++ b/src/main/java/com/youlai/system/config/SecurityConfig.java
@@ -1,11 +1,11 @@
package com.youlai.system.config;
import com.youlai.system.common.constant.SecurityConstants;
-import com.youlai.system.filter.JwtAuthenticationFilter;
import com.youlai.system.security.exception.MyAccessDeniedHandler;
import com.youlai.system.security.exception.MyAuthenticationEntryPoint;
-import com.youlai.system.security.JwtTokenManager;
+import com.youlai.system.security.jwt.JwtTokenFilter;
import com.youlai.system.filter.VerifyCodeFilter;
+import com.youlai.system.security.jwt.JwtTokenProvider;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -36,7 +36,7 @@ public class SecurityConfig {
private final MyAuthenticationEntryPoint authenticationEntryPoint;
private final MyAccessDeniedHandler accessDeniedHandler;
- private final JwtTokenManager jwtTokenManager;
+ private final JwtTokenProvider jwtTokenProvider;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
@@ -58,7 +58,7 @@ public class SecurityConfig {
// 验证码校验过滤器
http.addFilterBefore(new VerifyCodeFilter(),UsernamePasswordAuthenticationFilter.class);
// JWT 校验过滤器
- http.addFilterBefore(new JwtAuthenticationFilter(jwtTokenManager), UsernamePasswordAuthenticationFilter.class);
+ http.addFilterBefore(new JwtTokenFilter(jwtTokenProvider), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
diff --git a/src/main/java/com/youlai/system/controller/SysUserController.java b/src/main/java/com/youlai/system/controller/SysUserController.java
index 4b1a89bf..58f34846 100644
--- a/src/main/java/com/youlai/system/controller/SysUserController.java
+++ b/src/main/java/com/youlai/system/controller/SysUserController.java
@@ -7,7 +7,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.youlai.system.common.constant.ExcelConstants;
import com.youlai.system.common.result.PageResult;
import com.youlai.system.common.result.Result;
-import com.youlai.system.util.ExcelUtils;
+import com.youlai.system.common.util.ExcelUtils;
import com.youlai.system.common.annotation.PreventDuplicateSubmit;
import com.youlai.system.listener.easyexcel.UserImportListener;
import com.youlai.system.model.vo.UserImportVO;
diff --git a/src/main/java/com/youlai/system/filter/JwtAuthenticationFilter.java b/src/main/java/com/youlai/system/filter/JwtAuthenticationFilter.java
deleted file mode 100644
index 64364ae8..00000000
--- a/src/main/java/com/youlai/system/filter/JwtAuthenticationFilter.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.youlai.system.filter;
-
-import cn.hutool.core.util.StrUtil;
-import com.youlai.system.common.constant.SecurityConstants;
-import com.youlai.system.common.result.ResultCode;
-import com.youlai.system.util.RequestUtils;
-import com.youlai.system.util.ResponseUtils;
-import com.youlai.system.security.JwtTokenManager;
-import io.jsonwebtoken.Claims;
-import jakarta.servlet.FilterChain;
-import jakarta.servlet.ServletException;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
-import org.springframework.web.filter.OncePerRequestFilter;
-
-import java.io.IOException;
-
-/**
- * JWT 校验过滤器
- *
- * @author haoxr
- * @since 2022/10/1
- */
-public class JwtAuthenticationFilter extends OncePerRequestFilter {
-
- private static final AntPathRequestMatcher LOGIN_PATH_REQUEST_MATCHER = new AntPathRequestMatcher(SecurityConstants.LOGIN_PATH, "POST");
-
- private final JwtTokenManager tokenManager;
-
- public JwtAuthenticationFilter(JwtTokenManager tokenManager) {
- this.tokenManager = tokenManager;
- }
-
- @Override
- protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
- // 登录接口放行是走过滤器链的方式(验证码校验过滤器),这里拦截到登录接口需要手动放行
- if (LOGIN_PATH_REQUEST_MATCHER.matches(request)) {
- // 手动放行登录接口
- chain.doFilter(request, response);
- }else{
- String jwt = RequestUtils.resolveToken(request);
- if (StrUtil.isNotBlank(jwt) && SecurityContextHolder.getContext().getAuthentication() == null) {
- try {
- // 解析&验证 JWT
- Claims claims = this.tokenManager.parseAndValidateToken(jwt);
-
- // JWT验证有效获取Authentication存入Security上下文
- Authentication authentication = this.tokenManager.getAuthentication(claims);
- SecurityContextHolder.getContext().setAuthentication(authentication);
-
- chain.doFilter(request, response);
- }catch (Exception e){
- ResponseUtils.writeErrMsg(response, ResultCode.TOKEN_INVALID);
- }
- }else{
- ResponseUtils.writeErrMsg(response, ResultCode.TOKEN_INVALID);
- }
- }
- }
-}
diff --git a/src/main/java/com/youlai/system/filter/VerifyCodeFilter.java b/src/main/java/com/youlai/system/filter/VerifyCodeFilter.java
index bcae036d..3e6c5fb7 100644
--- a/src/main/java/com/youlai/system/filter/VerifyCodeFilter.java
+++ b/src/main/java/com/youlai/system/filter/VerifyCodeFilter.java
@@ -5,7 +5,7 @@ import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.youlai.system.common.constant.SecurityConstants;
import com.youlai.system.common.result.ResultCode;
-import com.youlai.system.util.ResponseUtils;
+import com.youlai.system.common.util.ResponseUtils;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
diff --git a/src/main/java/com/youlai/system/handler/mybatisplus/MyDataPermissionHandler.java b/src/main/java/com/youlai/system/handler/mybatisplus/MyDataPermissionHandler.java
index aa713b79..cb22cb64 100644
--- a/src/main/java/com/youlai/system/handler/mybatisplus/MyDataPermissionHandler.java
+++ b/src/main/java/com/youlai/system/handler/mybatisplus/MyDataPermissionHandler.java
@@ -7,7 +7,7 @@ import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
import com.youlai.system.common.annotation.DataPermission;
import com.youlai.system.common.base.IBaseEnum;
import com.youlai.system.common.enums.DataScopeEnum;
-import com.youlai.system.util.SecurityUtils;
+import com.youlai.system.common.util.SecurityUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
diff --git a/src/main/java/com/youlai/system/interceptor/AuthChannelInterceptor.java b/src/main/java/com/youlai/system/interceptor/AuthChannelInterceptor.java
index 38bc7f7b..149f5774 100644
--- a/src/main/java/com/youlai/system/interceptor/AuthChannelInterceptor.java
+++ b/src/main/java/com/youlai/system/interceptor/AuthChannelInterceptor.java
@@ -1,9 +1,7 @@
package com.youlai.system.interceptor;
import cn.hutool.core.util.StrUtil;
-import com.youlai.system.common.constant.SecurityConstants;
-import com.youlai.system.security.JwtTokenManager;
-import io.jsonwebtoken.Claims;
+import com.youlai.system.security.jwt.JwtTokenProvider;
import lombok.RequiredArgsConstructor;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
@@ -25,13 +23,13 @@ import java.security.Principal;
@RequiredArgsConstructor
public class AuthChannelInterceptor implements ChannelInterceptor {
- private final JwtTokenManager jwtTokenManager;
+ private final JwtTokenProvider jwtTokenProvider;
/**
* 连接前监听
*
- * @param message
- * @param channel
+ * @param message 消息
+ * @param channel 通道
* @return
*/
@Override
@@ -41,14 +39,12 @@ public class AuthChannelInterceptor implements ChannelInterceptor {
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
// get token from header
- String token = accessor.getFirstNativeHeader("Authorization");
+ String bearerToken = accessor.getFirstNativeHeader("Authorization");
// if token is not null
- if (StrUtil.isNotBlank(token)) {
+ if (StrUtil.isNotBlank(bearerToken)) {
- token = token.substring(SecurityConstants.TOKEN_PREFIX.length());
- Claims claims = jwtTokenManager.parseAndValidateToken(token);
-
- String username = claims.get("username", String.class);
+ bearerToken = bearerToken.substring(7);
+ String username = jwtTokenProvider.getUsername(bearerToken);
// if the username is not null, assign it to the Principal.
if (StrUtil.isNotBlank(username)) {
Principal principal = () -> username;
diff --git a/src/main/java/com/youlai/system/security/exception/MyAccessDeniedHandler.java b/src/main/java/com/youlai/system/security/exception/MyAccessDeniedHandler.java
index 78b0fbc8..83515d17 100644
--- a/src/main/java/com/youlai/system/security/exception/MyAccessDeniedHandler.java
+++ b/src/main/java/com/youlai/system/security/exception/MyAccessDeniedHandler.java
@@ -1,7 +1,7 @@
package com.youlai.system.security.exception;
import com.youlai.system.common.result.ResultCode;
-import com.youlai.system.util.ResponseUtils;
+import com.youlai.system.common.util.ResponseUtils;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/youlai/system/security/jwt/JwtTokenFilter.java b/src/main/java/com/youlai/system/security/jwt/JwtTokenFilter.java
new file mode 100644
index 00000000..8d03542b
--- /dev/null
+++ b/src/main/java/com/youlai/system/security/jwt/JwtTokenFilter.java
@@ -0,0 +1,44 @@
+package com.youlai.system.security.jwt;
+
+import com.youlai.system.common.result.ResultCode;
+import com.youlai.system.common.util.ResponseUtils;
+import com.youlai.system.exception.BusinessException;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import java.io.IOException;
+
+/**
+ * @author haoxr
+ * @since 2023/9/13
+ */
+public class JwtTokenFilter extends OncePerRequestFilter {
+ private JwtTokenProvider jwtTokenProvider;
+
+ public JwtTokenFilter(JwtTokenProvider jwtTokenProvider) {
+ this.jwtTokenProvider = jwtTokenProvider;
+ }
+
+ @Override
+ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
+ String token = jwtTokenProvider.resolveToken(request);
+ try {
+ if (token != null && jwtTokenProvider.validateToken(token)) {
+ Authentication auth = jwtTokenProvider.getAuthentication(token);
+ SecurityContextHolder.getContext().setAuthentication(auth);
+ }
+ } catch (BusinessException ex) {
+ //this is very important, since it guarantees the user is not authenticated at all
+ SecurityContextHolder.clearContext();
+ ResponseUtils.writeErrMsg(response,(ResultCode)ex.getResultCode());
+ return;
+ }
+
+ filterChain.doFilter(request, response);
+ }
+}
diff --git a/src/main/java/com/youlai/system/security/JwtTokenManager.java b/src/main/java/com/youlai/system/security/jwt/JwtTokenProvider.java
similarity index 52%
rename from src/main/java/com/youlai/system/security/JwtTokenManager.java
rename to src/main/java/com/youlai/system/security/jwt/JwtTokenProvider.java
index 20928dce..e5009b2f 100644
--- a/src/main/java/com/youlai/system/security/JwtTokenManager.java
+++ b/src/main/java/com/youlai/system/security/jwt/JwtTokenProvider.java
@@ -1,13 +1,17 @@
-package com.youlai.system.security;
+package com.youlai.system.security.jwt;
import cn.hutool.core.convert.Convert;
-import cn.hutool.core.util.IdUtil;
import com.youlai.system.common.constant.SecurityConstants;
import com.youlai.system.security.model.SysUserDetails;
-import io.jsonwebtoken.*;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.io.DecodingException;
import io.jsonwebtoken.security.Keys;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -15,62 +19,53 @@ import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;
-import jakarta.annotation.Resource;
import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
import java.util.stream.Collectors;
/**
- * JWT token 管理器
+ * JWT token 管理器
*
* @author haoxr
- * @since 2022/10/22
+ * @since 2023/9/13
*/
+
@Component
-public class JwtTokenManager {
-
- /**
- * token加密密钥
- */
- @Value("${auth.token.secret_key}")
- private String secretKey;
-
- /**
- * token有效期(单位:秒)
- */
- @Value("${auth.token.ttl}")
- private Long tokenTtl;
-
- /**
- * secret key byte array.
- */
- private byte[] secretKeyBytes;
-
- private JwtParser jwtParser;
+public class JwtTokenProvider {
@Resource
private RedisTemplate redisTemplate;
+ @Value("${jwt.secret-key:123456}")
+ private String secretKey;
+
+ @Value("${jwt.expiration:7200}")
+ private int expiration;
+
+ private byte[] secretKeyBytes;
+
+
+ @PostConstruct
+ protected void init() {
+ secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes());
+ }
+
/**
- * Create token.
+ * 创建Token
*
- * @param authentication auth info
- * @return token
+ * @param authentication
+ * @return
*/
public String createToken(Authentication authentication) {
Claims claims = Jwts.claims().setSubject(authentication.getName());
+
SysUserDetails userDetails = (SysUserDetails) authentication.getPrincipal();
- claims.put("jti",IdUtil.fastSimpleUUID());
claims.put("userId", userDetails.getUserId());
claims.put("username", claims.getSubject());
claims.put("deptId", userDetails.getDeptId());
claims.put("dataScope", userDetails.getDataScope());
- // 角色放入JWT的claims
Set