Kaynağa Gözat

fix: jwt token 校验secret不正确、过期异常

secret需要base64编码后
过期异常已经正常返回
370774330@qq.com 5 yıl önce
ebeveyn
işleme
e2bd9181b3

+ 0 - 5
common/src/main/java/seecoder/devcloud/common/util/JwtTokenUtil.java

@@ -39,11 +39,6 @@ public class JwtTokenUtil {
 
     private String secret;
 
-    private Long expiration;
-
-    /**
-     * 使用自己方法判断超时是为了后端可以在 小于等于门户过期时间的范围内,自由调控过期时间
-     */
     public Boolean isTokenExpired(String token) {
         try {
             Claims claims = getClaimsFromToken(token);

+ 0 - 29
web/src/main/java/seecoder/devcloud/web/dao/impl/UserMapperImpl.java

@@ -1,29 +0,0 @@
-package seecoder.devcloud.web.dao.impl;
-
-import org.springframework.security.core.context.SecurityContext;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.stereotype.Component;
-import seecoder.devcloud.web.dao.user.UserMapper;
-import seecoder.devcloud.web.model.po.user.User;
-
-/**
- * @author PuHong Weng
- * @date 2021/3/11
- * @description:
- */
-@Component
-public class UserMapperImpl implements UserMapper {
-
-
-    @Override
-    public User findLoginUser() {
-        User loginUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
-        return loginUser;
-    }
-
-    @Override
-    public User findUserByUsername(String username) {
-        //todo 从门户获取
-        return null;
-    }
-}

+ 0 - 22
web/src/main/java/seecoder/devcloud/web/dao/user/UserMapper.java

@@ -1,22 +0,0 @@
-package seecoder.devcloud.web.dao.user;
-
-import seecoder.devcloud.web.model.po.user.User;
-
-/**
- * 准确来说已经不是mybatis的mapper了
- * 因为集成了门户系统,用户数据需要从那取
- * 这里写成这种形式是为了不破坏三层结构
- */
-public interface UserMapper {
-
-	/**
-	 * 返回当前自己的用户信息
-	 * 由于集成了门户系统而且使用了jwt作为安全认证机制,自己的用户信息存放在 SecurityContextHolder中
-	 * 见 JwtAuthenticationTokenFilter.class
-	 * 注意:SecurityContextHolder采用的是ThreadLocal实现的
-	 *     如果要新开子线程,且子线程需要用到用户信息,务必在父线程把用户信息取出
-	 */
-	User findLoginUser();
-
-	User findUserByUsername(String username);
-}

+ 11 - 2
web/src/main/java/seecoder/devcloud/web/infrastructure/GlobalExceptionHandler.java

@@ -4,9 +4,11 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.ControllerAdvice;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
 import seecoder.devcloud.common.exceptions.AccessDeniedException;
 import seecoder.devcloud.common.exceptions.ConflictException;
 import seecoder.devcloud.common.exceptions.ServiceException;
+import seecoder.devcloud.web.infrastructure.security.TokenExpiredException;
 import seecoder.devcloud.web.model.vo.Response;
 
 /**
@@ -14,7 +16,7 @@ import seecoder.devcloud.web.model.vo.Response;
  * @date 2021/3/5
  * @description: 统一异常返回处理
  */
-@ControllerAdvice
+@RestControllerAdvice
 @Slf4j
 public class GlobalExceptionHandler {
 
@@ -27,8 +29,15 @@ public class GlobalExceptionHandler {
 
     @ExceptionHandler(Exception.class)
     @ResponseBody
-    public Response serviceExceptionHandler(Exception e){
+    public Response exceptionHandler(Exception e){
         log.error("Error: ",e);
         return Response.buildFailure(503,e.getMessage());
     }
+
+    @ExceptionHandler(TokenExpiredException.class)
+    @ResponseBody
+    public Response tokenExpiredExceptionHandler(TokenExpiredException e){
+        log.error("Error: ",e);
+        return Response.buildFailure(e.getCode(), e.getMessage());
+    }
 }

+ 10 - 8
web/src/main/java/seecoder/devcloud/web/infrastructure/security/JwtAuthenticationTokenFilter.java

@@ -23,6 +23,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.util.LinkedHashMap;
 
 
 /**
@@ -51,16 +52,16 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
             // 有token,验证正确性,签名不正确,会抛异常
             Claims claims = jwtTokenUtil.getClaimsFromToken(authHeader);
             if (claims != null){
+                LinkedHashMap<String,Object> userInfo = claims.get("user_info", LinkedHashMap.class);
                 UserDetails userDetails = User.builder()
-                        .id(claims.get("id",Integer.class))
-                        .username(claims.get("name",String.class))
-                        .email(claims.get("email",String.class))
-                        .phone(claims.get("phone",String.class))
-                        //todo 验证是否和门户身份一致
-                        .role(UserIdentity.valueOf(claims.get("role",String.class)))
+                        .id((Integer) userInfo.get("id"))
+                        .username((String) userInfo.get("name"))
+                        .email((String) userInfo.get("email"))
+                        .phone((String) userInfo.get("phone"))
+                        .role(UserIdentity.valueOf((String) userInfo.get("role")))
                         .build();
                 // 验证token是否过期
-                if (jwtTokenUtil.isTokenExpired(authHeader)) {
+                if (!jwtTokenUtil.isTokenExpired(authHeader)) {
                     //加载用户、角色、权限信息,Spring Security根据这些信息判断接口的访问权限
                     UsernamePasswordAuthenticationToken authentication
                             = new UsernamePasswordAuthenticationToken(userDetails, null,
@@ -73,15 +74,16 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
                     PrintWriter out = null ;
                     try{
                         httpServletResponse.setCharacterEncoding("UTF-8");
+                        httpServletResponse.setStatus(10010);
                         httpServletResponse.setContentType("application/json; charset=utf-8");
                         out = httpServletResponse.getWriter();
                         out.append(Response.buildFailure(10110,"Jwt token 过期").toString());
-                        return;
                     }
                     catch (Exception e){
                         e.printStackTrace();
                         httpServletResponse.sendError(500);
                     }
+                    return;
                 }
             }
 

+ 20 - 0
web/src/main/java/seecoder/devcloud/web/infrastructure/security/TokenExpiredException.java

@@ -0,0 +1,20 @@
+package seecoder.devcloud.web.infrastructure.security;
+
+import lombok.Data;
+import org.springframework.http.HttpStatus;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/14
+ * @description:
+ */
+@Data
+public class TokenExpiredException extends Exception{
+
+    private int code = 10010;
+
+    public TokenExpiredException() {
+        super("JWT Token 已过期");
+
+    }
+}

+ 3 - 5
web/src/main/java/seecoder/devcloud/web/service/impl/pipeline/PipelineServiceImpl.java

@@ -4,7 +4,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import seecoder.devcloud.web.dao.pipeline.PipelineHistoryMapper;
 import seecoder.devcloud.web.dao.pipeline.PipelineMapper;
-import seecoder.devcloud.web.dao.user.UserMapper;
 import seecoder.devcloud.web.model.po.pipeline.Pipeline;
 import seecoder.devcloud.web.model.po.pipeline.PipelineHistory;
 import seecoder.devcloud.web.model.po.user.User;
@@ -13,6 +12,7 @@ import seecoder.devcloud.web.model.vo.pipeline.PipelineCreateVO;
 import seecoder.devcloud.web.model.vo.pipeline.PipelineHistoryVO;
 import seecoder.devcloud.web.model.vo.pipeline.PipelineInfoVO;
 import seecoder.devcloud.web.service.pipeline.PipelineService;
+import seecoder.devcloud.web.service.user.UserService;
 
 import java.util.List;
 import java.util.Map;
@@ -30,14 +30,12 @@ public class PipelineServiceImpl implements PipelineService {
 
     private final PipelineMapper pipelineMapper;
 
-    private final UserMapper userMapper;
 
 
     @Autowired
-    public PipelineServiceImpl(PipelineHistoryMapper pipelineHistoryMapper, PipelineMapper pipelineMapper, UserMapper userMapper) {
+    public PipelineServiceImpl(PipelineHistoryMapper pipelineHistoryMapper, PipelineMapper pipelineMapper) {
         this.pipelineHistoryMapper = pipelineHistoryMapper;
         this.pipelineMapper = pipelineMapper;
-        this.userMapper = userMapper;
     }
 
 
@@ -95,7 +93,7 @@ public class PipelineServiceImpl implements PipelineService {
      * 防止用户修改提交的参数从而修改其他组的流水线
      */
     private void projectAuthentication(Integer projectId){
-        User user = userMapper.findLoginUser();
+        User user = UserService.loginUser();
         //todo 鉴权
 
     }

+ 5 - 5
web/src/main/java/seecoder/devcloud/web/service/impl/user/GroupServiceImpl.java

@@ -4,6 +4,8 @@ package seecoder.devcloud.web.service.impl.user;
 import lombok.extern.slf4j.Slf4j;
 import org.gitlab4j.api.GitLabApiException;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import seecoder.devcloud.api.gitlab.GitlabApi;
@@ -12,12 +14,12 @@ import seecoder.devcloud.common.exceptions.EntityNotFoundException;
 import seecoder.devcloud.common.exceptions.ServiceException;
 import seecoder.devcloud.web.dao.user.GroupMapper;
 import seecoder.devcloud.web.dao.user.GroupMemberMapper;
-import seecoder.devcloud.web.dao.user.UserMapper;
 import seecoder.devcloud.web.model.enums.GroupType;
 import seecoder.devcloud.web.model.po.user.Group;
 import seecoder.devcloud.web.model.po.user.User;
 import seecoder.devcloud.web.service.user.GroupService;
 import seecoder.devcloud.web.model.vo.user.GroupVO;
+import seecoder.devcloud.web.service.user.UserService;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -30,14 +32,12 @@ public class GroupServiceImpl implements GroupService {
     private final GroupMapper groupMapper;
     private final GroupMemberMapper groupMemberMapper;
     private final GitlabApi gitlabApi;
-    private final UserMapper userMapper;
 
     @Autowired
-    public GroupServiceImpl(GroupMapper groupMapper, GroupMemberMapper groupMemberMapper, GitlabApi gitlabApi, UserMapper userMapper) {
+    public GroupServiceImpl(GroupMapper groupMapper, GroupMemberMapper groupMemberMapper, GitlabApi gitlabApi) {
         this.groupMapper = groupMapper;
         this.groupMemberMapper = groupMemberMapper;
         this.gitlabApi = gitlabApi;
-        this.userMapper = userMapper;
     }
 
     @Override
@@ -46,7 +46,7 @@ public class GroupServiceImpl implements GroupService {
         if (groupMapper.findGroupByName(name) != null){
             throw new ServiceException("您创建的小组名字已被使用!");
         }
-        User user = userMapper.findLoginUser();
+        User user = UserService.loginUser();
         List<User> members = new ArrayList<>();
         members.add(user);
         GitlabGroup gitGroup;

+ 4 - 12
web/src/main/java/seecoder/devcloud/web/service/impl/user/UserServiceImpl.java

@@ -2,13 +2,13 @@ package seecoder.devcloud.web.service.impl.user;
 
 
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.security.core.userdetails.UsernameNotFoundException;
 import org.springframework.stereotype.Service;
 
-import seecoder.devcloud.web.dao.user.UserMapper;
+import seecoder.devcloud.web.model.po.user.User;
 import seecoder.devcloud.web.model.vo.user.UserVO;
 import seecoder.devcloud.web.service.user.UserService;
 
@@ -16,18 +16,10 @@ import seecoder.devcloud.web.service.user.UserService;
 @Slf4j
 public class UserServiceImpl implements UserService, UserDetailsService {
 
-
-
-	private final UserMapper userMapper;
-
-	@Autowired
-	public UserServiceImpl(UserMapper userMapper) {
-		this.userMapper = userMapper;
-	}
-
 	@Override
 	public UserVO getLoginUser(){
-		return new UserVO(userMapper.findLoginUser());
+		User loginUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+		return new UserVO(loginUser);
 	}
 
 

+ 8 - 1
web/src/main/java/seecoder/devcloud/web/service/user/UserService.java

@@ -1,11 +1,18 @@
 package seecoder.devcloud.web.service.user;
 
 
+import org.springframework.security.core.context.SecurityContextHolder;
+import seecoder.devcloud.web.model.po.user.User;
 import seecoder.devcloud.web.model.vo.user.UserVO;
 
 public interface UserService {
 
     UserVO getLoginUser();
 
-
+    /**
+     * 用于内部获取登🦌用户PO
+     */
+    static User loginUser(){
+        return (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+    }
 }

+ 1 - 3
web/src/main/resources/application-wph.yml

@@ -26,9 +26,7 @@ mybatis:
 
 seecoder:
   jwt:
-    secret: SEEC-1919810-OIDC-114514
-    expiration: 3600000
-
+    secret: U0VFQy0xOTE5ODEwLU9JREMtMTE0NTE0
   k8s:
     api-server: https://192.168.99.105:8443
     token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjBmSXc4RlRjNUpBYVpGYWc4QzRDY1MzUWJad1JMdFhKcDI1cngzWGtiRlkifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZXZjbG91ZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLXNicXY4Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI5NmIxNzU1ZS0zZjE3LTQ1ZTctODFmYi01MTRhODA3NDRhMzQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGV2Y2xvdWQ6ZGVmYXVsdCJ9.W0Y1lR6LBi1ZjylBx35YeqYuq2u2AqH-ayK4FD-LDfC26E89DanOwSv9XLrRMnnDBZFS_ZCRBumbnDeMiS5vw2x7-QnrDqj1M5u9FB2fIJsz2LyUkOhATZZmTzj_Uhewvvg09aDKh16ttj6ZX27m-KVk_6MP-VfiuvZnCVxDbqRkRjK-zsor4ty1CEATPyKK-tvugAwS0RFNHUL94DamfZAq_t1PSnH5ZtEHq0uEMZxY2c7j6u9d_aD9lphm_ZpCy_C8OCHfanM21CQPDHlcJTW_aiOO6bAp8qdc1egPO5uIamHl6Zm0N3RkcsRp4DGOHrltTV9y_cGZHXSWmRHfxw