瀏覽代碼

feat: 修改鉴权逻辑,web接口session查不到用户信息时根据header查询鉴权信息判断登录是否失效

weijianghai 2 年之前
父節點
當前提交
0c43710972

+ 7 - 1
src/main/java/com/nokia/config/web/MyWebMvcConfigurer.java

@@ -1,5 +1,6 @@
 package com.nokia.config.web;
 
+import com.nokia.service.AclService;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
@@ -13,13 +14,18 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 public class MyWebMvcConfigurer implements WebMvcConfigurer {
     @Value("${redis.timeoutSeconds:600}")
     private Integer timeoutSeconds;
+    private final AclService aclService;
+
+    public MyWebMvcConfigurer(AclService aclService) {
+        this.aclService = aclService;
+    }
 
     @Override
     public void addInterceptors(InterceptorRegistry registry) {
         // 添加请求日志拦截
         registry.addInterceptor(new RequestLogHandlerInterceptor()).addPathPatterns("/**");
         // 添加web登录拦截
-        registry.addInterceptor(new WebLoginInterceptor(timeoutSeconds)).addPathPatterns("/api/web/**");
+        registry.addInterceptor(new WebLoginInterceptor(timeoutSeconds, aclService)).addPathPatterns("/api/web/**");
     }
 
     /**

+ 12 - 8
src/main/java/com/nokia/config/web/RequestLogHandlerInterceptor.java

@@ -1,5 +1,6 @@
 package com.nokia.config.web;
 
+import com.alibaba.fastjson2.JSON;
 import lombok.extern.slf4j.Slf4j;
 import org.slf4j.MDC;
 import org.springframework.lang.Nullable;
@@ -11,6 +12,9 @@ import org.springframework.web.servlet.HandlerInterceptor;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.nio.charset.Charset;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.UUID;
 
 /**
@@ -33,14 +37,14 @@ public class RequestLogHandlerInterceptor implements HandlerInterceptor {
         MDC.put("traceId", UUID.randomUUID().toString().replace("-", ""));
         log.info("请求地址: {} {}", request.getRequestURL().toString(), request.getMethod());
         // 请求头参数
-//        Map<String, String> headers = new HashMap<>();
-//        Enumeration<String> headerNames = request.getHeaderNames();
-//        while (headerNames.hasMoreElements()) {
-//            String k	= headerNames.nextElement();
-//            String v = request.getHeader(k);
-//            headers.put(k, v);
-//        }
-//        log.info("请求头参数: {}", JSON.toJSONString(headers));
+        Map<String, String> headers = new HashMap<>();
+        Enumeration<String> headerNames = request.getHeaderNames();
+        while (headerNames.hasMoreElements()) {
+            String k	= headerNames.nextElement();
+            String v = request.getHeader(k);
+            headers.put(k, v);
+        }
+        log.info("请求头参数: {}", JSON.toJSONString(headers));
         // 查询参数
 //        Map<String, String> parameters = new HashMap<>();
 //        Enumeration<String> parameterNames = request.getParameterNames();

+ 29 - 7
src/main/java/com/nokia/config/web/WebLoginInterceptor.java

@@ -2,13 +2,17 @@ package com.nokia.config.web;
 
 import com.alibaba.fastjson2.JSON;
 import com.nokia.common.R;
+import com.nokia.service.AclService;
+import com.nokia.vo.TokenVo;
 import lombok.NoArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.web.servlet.HandlerInterceptor;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
+import java.io.IOException;
 
 /**
  * web登录拦截
@@ -17,21 +21,31 @@ import javax.servlet.http.HttpSession;
 @NoArgsConstructor
 public class WebLoginInterceptor implements HandlerInterceptor {
     private Integer timeoutSeconds;
+    private AclService aclService;
 
-    public WebLoginInterceptor(Integer timeoutSeconds) {
+    public WebLoginInterceptor(Integer timeoutSeconds, AclService aclService) {
         this.timeoutSeconds = timeoutSeconds;
+        this.aclService = aclService;
     }
 
     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
         HttpSession session = request.getSession();
         // 未登录或登录失效返回401
-        if (session == null || session.getAttribute("userinfo") == null) {
-            response.setCharacterEncoding("UTF-8");
-            response.setContentType("application/json; charset=utf-8");
-            byte[] bytes = JSON.toJSONString(R.error().code(401).message("登录失效")).getBytes();
-            response.getOutputStream().write(bytes);
-            return false;
+        String token = request.getHeader("X-Authorization-Token");
+        String system = request.getHeader("X-Authorization-system");
+        String fromSystem = request.getHeader("X-Authorization-fromSystem");
+        if (StringUtils.isAnyBlank(token, system, fromSystem)) {
+            return unauthorized(response);
+        }
+        // session中用户信息为空根据header查询鉴权信息
+        if (session.getAttribute("userinfo") == null) {
+            TokenVo tokenVo = new TokenVo(token, system, fromSystem);
+            // 获取鉴权信息不记录日志
+            R r = aclService.verifySystem(tokenVo, session, false);
+            if (Boolean.FALSE.equals(r.getSuccess())) {
+                return unauthorized(response);
+            }
         }
         // 没有权限返回403
         if (session.getAttribute("role") == null) {
@@ -48,4 +62,12 @@ public class WebLoginInterceptor implements HandlerInterceptor {
         session.setMaxInactiveInterval(timeoutSeconds);
         return true;
     }
+
+    private boolean unauthorized(HttpServletResponse response) throws IOException {
+        response.setCharacterEncoding("UTF-8");
+        response.setContentType("application/json; charset=utf-8");
+        byte[] bytes = JSON.toJSONString(R.error().code(401).message("登录失效")).getBytes();
+        response.getOutputStream().write(bytes);
+        return false;
+    }
 }

+ 1 - 1
src/main/java/com/nokia/controller/VerificationController.java

@@ -42,6 +42,6 @@ public class VerificationController {
     })
     @PostMapping("/verification")
     public R verifySystem(@Valid @RequestBody TokenVo tokenEntity, HttpSession session) {
-        return aclService.verifySystem(tokenEntity, session);
+        return aclService.verifySystem(tokenEntity, session, true);
     }
 }

+ 11 - 3
src/main/java/com/nokia/service/AclService.java

@@ -67,8 +67,14 @@ public class AclService {
         this.fileService = fileService;
     }
 
+    /**
+     * 鉴权
+     * @param tokenEntity 请求参数
+     * @param session 会话
+     * @param logVerification 是否记录日志
+     */
     @Transactional(rollbackFor = Exception.class)
-    public R verifySystem(TokenVo tokenEntity, HttpSession session) {
+    public R verifySystem(TokenVo tokenEntity, HttpSession session, boolean logVerification) {
         log.debug("sessionId: {}", session.getId());
         Map<String, String> map = new HashMap<>();
         if (tokenEntity.getFromSystem().equalsIgnoreCase("top")) {
@@ -131,8 +137,10 @@ public class AclService {
         Integer success = Boolean.TRUE.equals(r.getSuccess()) ? 1 : 0;
         String res = JSON.toJSONString(r);
         // redis保存新token信息,记录登录日志
-        logVerification(tokenEntity, userEntity, success, res);
-        log.info("{}登录{}", userEntity.getLoginName(), tokenEntity.getSystem());
+        if (logVerification) {
+            logVerification(tokenEntity, userEntity, success, res);
+            log.info("{}登录{}", userEntity.getLoginName(), tokenEntity.getSystem());
+        }
         return r;
     }
 

+ 4 - 0
src/main/java/com/nokia/vo/TokenVo.java

@@ -1,7 +1,9 @@
 package com.nokia.vo;
 
 import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
 import javax.validation.constraints.NotBlank;
 import java.io.Serializable;
@@ -10,6 +12,8 @@ import java.io.Serializable;
  * 无用实体类
  */
 @Data
+@NoArgsConstructor
+@AllArgsConstructor
 public class TokenVo implements Serializable {
     @Schema(description = "token", required = true, example = "test_token_hebei")
     @NotBlank(message = "token不能为空")

+ 11 - 0
src/test/java/com/nokia/OtherTest.java

@@ -35,6 +35,17 @@ class OtherTest {
     @Autowired
     private RedisTemplate<String, Object> redisTemplate;
 
+    /**
+     * 测试删除token
+     */
+    @Test
+    void testDeleteToken() {
+        String system = "permission";
+        String token = "test_token_hebei";
+        String key = system + ":" + token;
+        redisTemplate.delete(key);
+    }
+
     @Test
     void testSplitAddress() {
         String inputPath = "test/org1.csv";