From acf448e980ed9eceeffc21c5d6174e5cb690c9b0 Mon Sep 17 00:00:00 2001
From: winter <2436197699@qq.com>
Date: Fri, 29 Mar 2024 10:37:43 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E9=A2=9D=E5=A4=96=E5=AF=B9=E5=9B=BD?=
=?UTF-8?q?=E5=9F=B9AI=E5=AF=B9=E8=AF=9D=E6=8E=A5=E5=8F=A3=E7=9A=84?=
=?UTF-8?q?=E9=89=B4=E6=9D=83?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pom.xml | 5 ++
.../exception/GlobalExceptionHandler.java | 2 +-
.../intercepter/UploadApiLogInterceptor.java | 18 +++-
.../controller/frontend/AiController.java | 2 +-
.../{ => notification}/DingAlertNotifier.java | 88 +++++++++----------
.../NotificationService.java | 32 +++----
.../manager/wx/MiniProgramSevice.java | 12 +++
.../security/SecurityConfiguration.java | 22 ++++-
.../security/filter/ApiAuthTokenFilter.java | 54 ++++++++++++
.../security/utils/JwtTokenUtil.java | 8 +-
src/main/resources/application.yml | 1 +
.../TeamModelExtensionApplicationTests.java | 2 +-
.../java/cn/teammodel/TestWithoutSpring.java | 21 ++++-
13 files changed, 192 insertions(+), 75 deletions(-)
rename src/main/java/cn/teammodel/manager/{ => notification}/DingAlertNotifier.java (95%)
rename src/main/java/cn/teammodel/manager/{ => notification}/NotificationService.java (83%)
create mode 100644 src/main/java/cn/teammodel/manager/wx/MiniProgramSevice.java
create mode 100644 src/main/java/cn/teammodel/security/filter/ApiAuthTokenFilter.java
diff --git a/pom.xml b/pom.xml
index eecb39b..2451f1b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -32,6 +32,11 @@
org.springframework.boot
spring-boot-starter-aop
+
+ com.github.binarywang
+ weixin-java-miniapp
+ 4.6.0
+
org.springframework.boot
diff --git a/src/main/java/cn/teammodel/config/exception/GlobalExceptionHandler.java b/src/main/java/cn/teammodel/config/exception/GlobalExceptionHandler.java
index dc02b4b..1b4abcc 100644
--- a/src/main/java/cn/teammodel/config/exception/GlobalExceptionHandler.java
+++ b/src/main/java/cn/teammodel/config/exception/GlobalExceptionHandler.java
@@ -2,7 +2,7 @@ package cn.teammodel.config.exception;
import cn.teammodel.common.ErrorCode;
import cn.teammodel.common.R;
-import cn.teammodel.manager.NotificationService;
+import cn.teammodel.manager.notification.NotificationService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.http.converter.HttpMessageNotReadableException;
diff --git a/src/main/java/cn/teammodel/config/intercepter/UploadApiLogInterceptor.java b/src/main/java/cn/teammodel/config/intercepter/UploadApiLogInterceptor.java
index 2f660a7..24a20d7 100644
--- a/src/main/java/cn/teammodel/config/intercepter/UploadApiLogInterceptor.java
+++ b/src/main/java/cn/teammodel/config/intercepter/UploadApiLogInterceptor.java
@@ -3,7 +3,7 @@ package cn.teammodel.config.intercepter;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.jwt.JWTUtil;
-import cn.teammodel.manager.NotificationService;
+import cn.teammodel.manager.notification.NotificationService;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
@@ -11,6 +11,8 @@ import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
@@ -32,13 +34,22 @@ import java.util.List;
@Component
@Slf4j
public class UploadApiLogInterceptor implements HandlerInterceptor {
+ @Value("${spring.env}")
+ private String env;
@Resource
private NotificationService notificationService;
private final ObjectMapper mapper = new ObjectMapper();
@Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+ public boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws Exception {
+ if (!env.equals("dev")) {
+ doUploadLog(request);
+ }
+ return true;
+ }
+
+ private void doUploadLog(@NotNull HttpServletRequest request) throws IOException {
String ip = ServletUtil.getClientIP(request);
String client = "";
String tokenSha = "";
@@ -115,7 +126,7 @@ public class UploadApiLogInterceptor implements HandlerInterceptor {
okHttpClient.newCall(okRequest).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
- log.error("UploadApiLogIntercepter error" ) ;
+ log.error("UploadApiLogIntercepter error") ;
notificationService.send("日志上传告警: 请求发送失败,检查请求发送客户端");
}
@@ -129,6 +140,5 @@ public class UploadApiLogInterceptor implements HandlerInterceptor {
}
}
});
- return true;
}
}
diff --git a/src/main/java/cn/teammodel/controller/frontend/AiController.java b/src/main/java/cn/teammodel/controller/frontend/AiController.java
index 141b7e4..db380ec 100644
--- a/src/main/java/cn/teammodel/controller/frontend/AiController.java
+++ b/src/main/java/cn/teammodel/controller/frontend/AiController.java
@@ -20,7 +20,7 @@ import java.util.List;
import java.util.concurrent.CompletableFuture;
@RestController
-@RequestMapping("public/ai")
+@RequestMapping("/ai/api")
@Api(tags = "AI 能力")
public class AiController {
@Resource
diff --git a/src/main/java/cn/teammodel/manager/DingAlertNotifier.java b/src/main/java/cn/teammodel/manager/notification/DingAlertNotifier.java
similarity index 95%
rename from src/main/java/cn/teammodel/manager/DingAlertNotifier.java
rename to src/main/java/cn/teammodel/manager/notification/DingAlertNotifier.java
index cdf5f22..96727d4 100644
--- a/src/main/java/cn/teammodel/manager/DingAlertNotifier.java
+++ b/src/main/java/cn/teammodel/manager/notification/DingAlertNotifier.java
@@ -1,44 +1,44 @@
-package cn.teammodel.manager;
-
-import com.dingtalk.api.DefaultDingTalkClient;
-import com.dingtalk.api.DingTalkClient;
-import com.dingtalk.api.request.OapiRobotSendRequest;
-import com.taobao.api.ApiException;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-
-/**
- * 钉钉告警服务
- * @author winter
- * @create 2023-11-14 10:11
- */
-@Component
-@Slf4j
-public class DingAlertNotifier implements NotificationService{
- private final DingTalkClient client;
- @Autowired
- public DingAlertNotifier(@Value("${ding.server-url}") String dingServerUrl) {
- this.client = new DefaultDingTalkClient(dingServerUrl);
- }
-
- @Override
- public void send(String message) {
- OapiRobotSendRequest request = new OapiRobotSendRequest();
- // 文本消息
- request.setMsgtype("text");
- OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
- text.setContent(message);
- request.setText(text);
- // at 管理员提醒异常
- OapiRobotSendRequest.At atAll = new OapiRobotSendRequest.At();
- atAll.setIsAtAll(true);
- request.setAt(atAll);
- try {
- client.execute(request);
- } catch (ApiException e) {
- log.error("钉钉 robot 推送消息渠道异常: {}", e.getMessage());
- }
- }
-}
+package cn.teammodel.manager.notification;
+
+import com.dingtalk.api.DefaultDingTalkClient;
+import com.dingtalk.api.DingTalkClient;
+import com.dingtalk.api.request.OapiRobotSendRequest;
+import com.taobao.api.ApiException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ * 钉钉告警服务
+ * @author winter
+ * @create 2023-11-14 10:11
+ */
+@Component
+@Slf4j
+public class DingAlertNotifier implements NotificationService{
+ private final DingTalkClient client;
+ @Autowired
+ public DingAlertNotifier(@Value("${ding.server-url}") String dingServerUrl) {
+ this.client = new DefaultDingTalkClient(dingServerUrl);
+ }
+
+ @Override
+ public void send(String message) {
+ OapiRobotSendRequest request = new OapiRobotSendRequest();
+ // 文本消息
+ request.setMsgtype("text");
+ OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
+ text.setContent(message);
+ request.setText(text);
+ // at 管理员提醒异常
+ OapiRobotSendRequest.At atAll = new OapiRobotSendRequest.At();
+ atAll.setIsAtAll(true);
+ request.setAt(atAll);
+ try {
+ client.execute(request);
+ } catch (ApiException e) {
+ log.error("钉钉 robot 推送消息渠道异常: {}", e.getMessage());
+ }
+ }
+}
diff --git a/src/main/java/cn/teammodel/manager/NotificationService.java b/src/main/java/cn/teammodel/manager/notification/NotificationService.java
similarity index 83%
rename from src/main/java/cn/teammodel/manager/NotificationService.java
rename to src/main/java/cn/teammodel/manager/notification/NotificationService.java
index f002ea4..e2c96da 100644
--- a/src/main/java/cn/teammodel/manager/NotificationService.java
+++ b/src/main/java/cn/teammodel/manager/notification/NotificationService.java
@@ -1,16 +1,16 @@
-package cn.teammodel.manager;
-
-/**
- * 消息通知接口
- * @author winter
- * @create 2023-11-14 10:08
- */
-public interface NotificationService {
-
- /**
- * 发送消息
- * @author: winter
- * @date: 2023/11/14 10:09
- */
- void send(String message);
-}
+package cn.teammodel.manager.notification;
+
+/**
+ * 消息通知接口
+ * @author winter
+ * @create 2023-11-14 10:08
+ */
+public interface NotificationService {
+
+ /**
+ * 发送消息
+ * @author: winter
+ * @date: 2023/11/14 10:09
+ */
+ void send(String message);
+}
diff --git a/src/main/java/cn/teammodel/manager/wx/MiniProgramSevice.java b/src/main/java/cn/teammodel/manager/wx/MiniProgramSevice.java
new file mode 100644
index 0000000..aa9e914
--- /dev/null
+++ b/src/main/java/cn/teammodel/manager/wx/MiniProgramSevice.java
@@ -0,0 +1,12 @@
+package cn.teammodel.manager.wx;
+
+import org.springframework.stereotype.Service;
+
+/**
+ * @author winter
+ * @create 2024-03-26 11:08
+ */
+@Service
+public class MiniProgramSevice {
+
+}
diff --git a/src/main/java/cn/teammodel/security/SecurityConfiguration.java b/src/main/java/cn/teammodel/security/SecurityConfiguration.java
index 93c7ff3..17114fa 100644
--- a/src/main/java/cn/teammodel/security/SecurityConfiguration.java
+++ b/src/main/java/cn/teammodel/security/SecurityConfiguration.java
@@ -1,10 +1,12 @@
package cn.teammodel.security;
+import cn.teammodel.security.filter.ApiAuthTokenFilter;
import cn.teammodel.security.filter.AuthInnerTokenFilter;
import cn.teammodel.security.handler.RestAccessDeniedHandler;
import cn.teammodel.security.handler.RestAuthenticationEntryPoint;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@@ -31,8 +33,11 @@ public class SecurityConfiguration {
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
@Resource
private AuthInnerTokenFilter authInnerTokenFilter;
+ @Resource
+ private ApiAuthTokenFilter apiAuthTokenFilter;
@Bean
+ @Order(2)
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// CSRF禁用,因为不使用session
@@ -64,7 +69,18 @@ public class SecurityConfiguration {
.exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint)
.accessDeniedHandler(restAccessDeniedHandler);
-
+ return http.build();
+ }
+ @Bean
+ @Order(1)
+ public SecurityFilterChain outterApiFilterChain(HttpSecurity http) throws Exception {
+ http.
+ antMatcher("/ai/api/**")
+ .authorizeRequests(authorizeRequests ->
+ authorizeRequests
+ .anyRequest().authenticated()
+ )
+ .addFilterAfter(apiAuthTokenFilter, BearerTokenAuthenticationFilter.class);
return http.build();
}
@@ -86,8 +102,8 @@ public class SecurityConfiguration {
}
/**
- * 跨域配置
- */
+ * 跨域配置
+ */
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
diff --git a/src/main/java/cn/teammodel/security/filter/ApiAuthTokenFilter.java b/src/main/java/cn/teammodel/security/filter/ApiAuthTokenFilter.java
new file mode 100644
index 0000000..92636f1
--- /dev/null
+++ b/src/main/java/cn/teammodel/security/filter/ApiAuthTokenFilter.java
@@ -0,0 +1,54 @@
+package cn.teammodel.security.filter;
+
+import cn.teammodel.security.utils.JwtTokenUtil;
+import io.jsonwebtoken.Claims;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.annotation.Resource;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * 对外的 AI chat 接口的认证过滤器
+ * @author winter
+ * @create 2023-11-09 10:43
+ */
+@Component
+@Slf4j
+public class ApiAuthTokenFilter extends OncePerRequestFilter {
+
+ @Resource
+ private JwtTokenUtil jwtTokenUtil;
+
+ // todo: 修改 context 的值 + 写一下多过滤器链的复盘
+ @Override
+ protected void doFilterInternal(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull FilterChain filterChain) throws ServletException, IOException {
+ SecurityContext context = SecurityContextHolder.getContext();
+ // 验证 authToken 合法
+ String token = request.getHeader("token");
+ if (StringUtils.isBlank(token)) {
+ filterChain.doFilter(request, response);
+ return;
+ }
+ Claims claims = jwtTokenUtil.validAndGetClaims(token, "fXO6ko/qyXeYrkecPeKdgXnuLXf9vMEtnBC9OB3s+aA=", 315360000);
+ if (claims == null) {
+ SecurityContextHolder.clearContext(); // 验证失败不应该在此处抛出异常,应该维护好 context 的值,以便整个过滤器链正常运行
+ filterChain.doFilter(request, response);
+ return;
+ }
+ // 组装 authToken 的 jwt 进 authentication
+ UsernamePasswordAuthenticationToken finalAuthentication = new UsernamePasswordAuthenticationToken(claims, null, null);
+ context.setAuthentication(finalAuthentication);
+ filterChain.doFilter(request, response);
+ }
+}
diff --git a/src/main/java/cn/teammodel/security/utils/JwtTokenUtil.java b/src/main/java/cn/teammodel/security/utils/JwtTokenUtil.java
index 027388d..902467c 100644
--- a/src/main/java/cn/teammodel/security/utils/JwtTokenUtil.java
+++ b/src/main/java/cn/teammodel/security/utils/JwtTokenUtil.java
@@ -74,11 +74,15 @@ public class JwtTokenUtil {
* @return claims或者null
*/
private Claims getClaimsFromToken(String token) {
+ return validAndGetClaims(token, secret, NEVER_EXPIRE);
+ }
+
+ public Claims validAndGetClaims(String token, String key, long expire) {
Claims claims = null;
try {
claims = Jwts.parser()
- .setSigningKey(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"))
- .setAllowedClockSkewSeconds(NEVER_EXPIRE)
+ .setSigningKey(new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256"))
+ .setAllowedClockSkewSeconds(expire)
.parseClaimsJws(token)
.getBody();
} catch (Exception e) {
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index e505ad2..fe0b1d2 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -1,4 +1,5 @@
spring:
+ env: dev
mvc:
pathmatch:
matching-strategy: ant_path_matcher
diff --git a/src/test/java/cn/teammodel/TeamModelExtensionApplicationTests.java b/src/test/java/cn/teammodel/TeamModelExtensionApplicationTests.java
index 855f9b8..da564bd 100644
--- a/src/test/java/cn/teammodel/TeamModelExtensionApplicationTests.java
+++ b/src/test/java/cn/teammodel/TeamModelExtensionApplicationTests.java
@@ -3,7 +3,7 @@ package cn.teammodel;
import cn.teammodel.common.PK;
import cn.teammodel.controller.admin.service.AdminAppraiseService;
import cn.teammodel.repository.*;
-import cn.teammodel.manager.DingAlertNotifier;
+import cn.teammodel.manager.notification.DingAlertNotifier;
import cn.teammodel.model.dto.admin.appraise.TimeRangeDto;
import cn.teammodel.model.dto.admin.appraise.UpdateAchievementRuleDto;
import cn.teammodel.model.entity.appraise.*;
diff --git a/src/test/java/cn/teammodel/TestWithoutSpring.java b/src/test/java/cn/teammodel/TestWithoutSpring.java
index 0bd297d..a047478 100644
--- a/src/test/java/cn/teammodel/TestWithoutSpring.java
+++ b/src/test/java/cn/teammodel/TestWithoutSpring.java
@@ -1,6 +1,5 @@
package cn.teammodel;
-import cn.hutool.jwt.JWTUtil;
import cn.teammodel.common.FiveEducations;
import cn.teammodel.model.entity.appraise.Appraise;
import cn.teammodel.model.entity.appraise.AppraiseTreeNode;
@@ -12,9 +11,13 @@ import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiRobotSendRequest;
import com.dingtalk.api.response.OapiRobotSendResponse;
import com.taobao.api.ApiException;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
@@ -33,8 +36,20 @@ public class TestWithoutSpring {
@Test
public void testJwtDecode() {
// 解析 JWT,不验证签
- Object roles = JWTUtil.parseToken("eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IlR4OFo1d2lkT2VSdDVCSGdWX2lvdXpzbjd6OCJ9.eyJhdWQiOiI3MjY0MzcwNC1iMmU3LTRiMjYtYjg4MS1iZDU4NjVlN2E3YTUiLCJpc3MiOiJodHRwczovL2xvZ2luLnBhcnRuZXIubWljcm9zb2Z0b25saW5lLmNuLzQ4MDdlOWNmLTg3YjgtNDE3NC1hYTViLWU3NjQ5N2Q3MzkyYi92Mi4wIiwiaWF0IjoxNzEwNzQ0MzA4LCJuYmYiOjE3MTA3NDQzMDgsImV4cCI6MTcxMDc0ODIwOCwiYWlvIjoiNDJaZ1lPQS9KL0t0ZTIzdWFzN2dEMGFPdW80WHpmdjlmMXhUREp6ZlZsNzk0VWkwWndVQSIsImF6cCI6ImM3MzE3Zjg4LTdjZWEtNGU0OC1hYzU3LWExNjA3MWY3Yjg4NCIsImF6cGFjciI6IjEiLCJvaWQiOiJkNDliYjc4Mi02ZGMyLTQ5MzktODY3OC1kMzNjMjY3MTliZjkiLCJyaCI6IjAuREFJQXota0hTTGlIZEVHcVctZGtsOWM1S3dRM1pITG5zaVpMdUlHOVdHWG5wNlVCQUFBLiIsInJvbGVzIjpbIklFUyJdLCJzdWIiOiJkNDliYjc4Mi02ZGMyLTQ5MzktODY3OC1kMzNjMjY3MTliZjkiLCJ0aWQiOiI0ODA3ZTljZi04N2I4LTQxNzQtYWE1Yi1lNzY0OTdkNzM5MmIiLCJ1dGkiOiJ6MGhKdDg0c1UwMlpxNTJNdGNRS0FBIiwidmVyIjoiMi4wIn0.U9KWPccJQ4ZgfzHBNTK6swuEJvkZM8ebfrOpAl7uDoNynlVEsp8CcQ2a1PIO3V8X8tcNassCplc08qbCqcL49R3S5vP2bWTiucT7c_fyCogxMYpmRM0RmGz8RF1tFF3VAxG4_q1Gt9LgzLbNhxxCQcbgJuZhUMKAP246esHlJrkue88FwgmMxf_rwxDH8VwbAchHtSuIRbj3zYSzgKU0Lpmibrr88g_gQZ061f4RyRezTmKLoOqhoGjEosOOnXOdI67YyxpdMjm64uzc92fNUyC9PHvu8XbTTbdUlkU2lPgrk5xFfyVus9SdxWQXB4PCIDhcBsoVQQlWGmY-kvw_8w").getPayload("roles");
- System.out.println(roles);
+ // Object roles = JWTUtil.parseToken("eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IlR4OFo1d2lkT2VSdDVCSGdWX2lvdXpzbjd6OCJ9.eyJhdWQiOiI3MjY0MzcwNC1iMmU3LTRiMjYtYjg4MS1iZDU4NjVlN2E3YTUiLCJpc3MiOiJodHRwczovL2xvZ2luLnBhcnRuZXIubWljcm9zb2Z0b25saW5lLmNuLzQ4MDdlOWNmLTg3YjgtNDE3NC1hYTViLWU3NjQ5N2Q3MzkyYi92Mi4wIiwiaWF0IjoxNzEwNzQ0MzA4LCJuYmYiOjE3MTA3NDQzMDgsImV4cCI6MTcxMDc0ODIwOCwiYWlvIjoiNDJaZ1lPQS9KL0t0ZTIzdWFzN2dEMGFPdW80WHpmdjlmMXhUREp6ZlZsNzk0VWkwWndVQSIsImF6cCI6ImM3MzE3Zjg4LTdjZWEtNGU0OC1hYzU3LWExNjA3MWY3Yjg4NCIsImF6cGFjciI6IjEiLCJvaWQiOiJkNDliYjc4Mi02ZGMyLTQ5MzktODY3OC1kMzNjMjY3MTliZjkiLCJyaCI6IjAuREFJQXota0hTTGlIZEVHcVctZGtsOWM1S3dRM1pITG5zaVpMdUlHOVdHWG5wNlVCQUFBLiIsInJvbGVzIjpbIklFUyJdLCJzdWIiOiJkNDliYjc4Mi02ZGMyLTQ5MzktODY3OC1kMzNjMjY3MTliZjkiLCJ0aWQiOiI0ODA3ZTljZi04N2I4LTQxNzQtYWE1Yi1lNzY0OTdkNzM5MmIiLCJ1dGkiOiJ6MGhKdDg0c1UwMlpxNTJNdGNRS0FBIiwidmVyIjoiMi4wIn0.U9KWPccJQ4ZgfzHBNTK6swuEJvkZM8ebfrOpAl7uDoNynlVEsp8CcQ2a1PIO3V8X8tcNassCplc08qbCqcL49R3S5vP2bWTiucT7c_fyCogxMYpmRM0RmGz8RF1tFF3VAxG4_q1Gt9LgzLbNhxxCQcbgJuZhUMKAP246esHlJrkue88FwgmMxf_rwxDH8VwbAchHtSuIRbj3zYSzgKU0Lpmibrr88g_gQZ061f4RyRezTmKLoOqhoGjEosOOnXOdI67YyxpdMjm64uzc92fNUyC9PHvu8XbTTbdUlkU2lPgrk5xFfyVus9SdxWQXB4PCIDhcBsoVQQlWGmY-kvw_8w").getPayload("roles");
+ // System.out.println(roles);
+
+ Claims claims = null;
+ try {
+ claims = Jwts.parser()
+ .setSigningKey(new SecretKeySpec("fXO6ko/qyXeYrkecPeKdgXnuLXf9vMEtnBC9OB3s+aA=".getBytes(StandardCharsets.UTF_8), "HmacSHA256"))
+ .setAllowedClockSkewSeconds(315360000)
+ .parseClaimsJws("eyJhbGciOiJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNobWFjLXNoYTI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ3d3cud2ludGVhY2guY24iLCJzdWIiOiI1NTUzMzMwNzQ1OTU4NzY4NjQiLCJleHAiOiIxNzExNjE1MDIxIiwibmFtZSI6IuWRqOWTjeWGmyIsInBpY3R1cmUiOm51bGwsImNkanhqeSI6eyJuaWNrbmFtZSI6IuWRqOWTjeWGmyIsInBpY3R1cmUiOm51bGwsImJpbmRJZCI6IjE4NDgyMTMzMDk0Iiwib3BlbmlkIjpudWxsLCJ1bmlvbmlkIjoiMWE4ZWFkNDYtY2JkMS00Y2VlLTg2NzEtZTU0NmMwZmQ4NTMyIn19._6ltuihVcWopQQqfgpSLo3aMVKE3MJhb28NQBSL_w7s")
+ .getBody();
+ System.out.println(claims);
+ } catch (Exception e) {
+ log.warn("token 解析出错:{}",e.getMessage());
+ }
}
@Test