From 28701115dd5ec9639c8df9d92e3154e6e4cdce91 Mon Sep 17 00:00:00 2001
From: click33 <2393584716@qq.com>
Date: Mon, 5 Sep 2022 06:49:49 +0800
Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=8D=95=E5=85=83=E6=B5=8B?=
=?UTF-8?q?=E8=AF=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/cn/dev33/satoken/id/SaIdUtil.java | 2 +
.../cn/dev33/satoken/router/SaRouter.java | 35 +---
.../cn/dev33/satoken/router/SaRouterUtil.java | 143 --------------
.../core/application/SaApplicationTest.java | 75 ++++++++
.../core/context/model/SaCookieTest.java | 12 +-
.../satoken/core/session/TokenSignTest.java | 29 +++
.../integrate/configure/HandlerException.java | 7 +
.../integrate/id/SaIdTokenController.java | 39 ++++
.../integrate/id/SaIdTokenControllerTest.java | 130 +++++++++++++
.../integrate/login/LoginControllerTest.java | 6 +-
.../integrate/more/MoreController.java | 40 ++++
.../integrate/more/MoreControllerTest.java | 97 ++++++++++
.../integrate/router/RouterController.java | 28 +++
.../router/RouterControllerTest.java | 179 ++++++++++++++++++
.../integrate/router/SaTokenConfigure2.java | 79 ++++++++
15 files changed, 722 insertions(+), 179 deletions(-)
delete mode 100644 sa-token-core/src/main/java/cn/dev33/satoken/router/SaRouterUtil.java
create mode 100644 sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/core/application/SaApplicationTest.java
create mode 100644 sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/core/session/TokenSignTest.java
create mode 100644 sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/id/SaIdTokenController.java
create mode 100644 sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/id/SaIdTokenControllerTest.java
create mode 100644 sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/more/MoreController.java
create mode 100644 sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/more/MoreControllerTest.java
create mode 100644 sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/router/RouterController.java
create mode 100644 sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/router/RouterControllerTest.java
create mode 100644 sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/router/SaTokenConfigure2.java
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/id/SaIdUtil.java b/sa-token-core/src/main/java/cn/dev33/satoken/id/SaIdUtil.java
index 79c6c325..af822348 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/id/SaIdUtil.java
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/id/SaIdUtil.java
@@ -6,6 +6,8 @@ package cn.dev33.satoken.id;
*
*/
public class SaIdUtil {
+
+ private SaIdUtil(){}
/**
* 在 Request 上储存 Id-Token 时建议使用的key
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/router/SaRouter.java b/sa-token-core/src/main/java/cn/dev33/satoken/router/SaRouter.java
index af4f4a23..41c1e91b 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/router/SaRouter.java
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/router/SaRouter.java
@@ -17,6 +17,9 @@ import cn.dev33.satoken.fun.SaParamRetFunction;
*/
public class SaRouter {
+ private SaRouter() {
+ }
+
// -------------------- 路由匹配相关 --------------------
/**
@@ -319,36 +322,4 @@ public class SaRouter {
throw new BackResultException(result);
}
-
- // -------------------- 历史API兼容 --------------------
-
- /**
- *
本函数设计已过时,请更换为:SaRouter.match(path...).ckeck(fun)
- * 路由匹配,如果匹配成功则执行认证函数
- * @param patterns 路由匹配符集合
- * @param function 要执行的方法
- */
- @Deprecated
- public static void match(List patterns, SaFunction function) {
- if(isMatchCurrURI(patterns)) {
- function.run();
- }
- }
-
- /**
- * 本函数设计已过时,请更换为:SaRouter.match(path...).notMatch(path...).ckeck(fun)
- * 路由匹配 (并指定排除匹配符),如果匹配成功则执行认证函数
- * @param patterns 路由匹配符集合
- * @param excludePatterns 要排除的路由匹配符集合
- * @param function 要执行的方法
- */
- @Deprecated
- public static void match(List patterns, List excludePatterns, SaFunction function) {
- if(isMatchCurrURI(patterns)) {
- if(isMatchCurrURI(excludePatterns) == false) {
- function.run();
- }
- }
- }
-
}
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/router/SaRouterUtil.java b/sa-token-core/src/main/java/cn/dev33/satoken/router/SaRouterUtil.java
deleted file mode 100644
index ce199a61..00000000
--- a/sa-token-core/src/main/java/cn/dev33/satoken/router/SaRouterUtil.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package cn.dev33.satoken.router;
-
-import java.util.Arrays;
-import java.util.List;
-
-import cn.dev33.satoken.SaManager;
-import cn.dev33.satoken.context.SaHolder;
-import cn.dev33.satoken.exception.StopMatchException;
-import cn.dev33.satoken.fun.IsRunFunction;
-import cn.dev33.satoken.fun.SaFunction;
-
-/**
- * 本类设计已过时,未来版本可能移除此类,请及时更换为 SaRouter ,使用方式保持不变
- * 对路由匹配符相关操作的封装工具类
- * @author kong
- *
- */
-@Deprecated
-public class SaRouterUtil {
-
- // -------------------- 路由匹配相关 --------------------
-
- /**
- * 校验指定路由匹配符是否可以匹配成功指定路径
- * @param pattern 路由匹配符
- * @param path 需要匹配的路径
- * @return 是否匹配成功
- */
- public static boolean isMatch(String pattern, String path) {
- return SaManager.getSaTokenContextOrSecond().matchPath(pattern, path);
- }
-
- /**
- * 校验指定路由匹配符是否可以匹配成功指定路径
- * @param patterns 路由匹配符
- * @param path 需要匹配的路径集合
- * @return 是否匹配成功
- */
- public static boolean isMatch(List patterns, String path) {
- for (String pattern : patterns) {
- if(isMatch(pattern, path)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * 校验指定路由匹配符是否可以匹配成功当前URI
- * @param pattern 路由匹配符
- * @return 是否匹配成功
- */
- public static boolean isMatchCurrURI(String pattern) {
- return isMatch(pattern, SaHolder.getRequest().getRequestPath());
- }
-
- /**
- * 校验指定路由匹配符是否可以匹配成功当前URI
- * @param patterns 路由匹配符
- * @return 是否匹配成功
- */
- public static boolean isMatchCurrURI(List patterns) {
- return isMatch(patterns, SaHolder.getRequest().getRequestPath());
- }
-
-
- // -------------------- 执行相关 --------------------
-
- /**
- * 使用路由匹配符与当前URI执行匹配,如果匹配成功则执行验证函数
- * @param pattern 路由匹配符
- * @param function 要执行的方法
- */
- public static void match(String pattern, SaFunction function) {
- if(isMatchCurrURI(pattern)) {
- function.run();
- }
- }
-
- /**
- * 使用路由匹配符与当前URI执行匹配 (并指定排除匹配符),如果匹配成功则执行验证函数
- * @param pattern 路由匹配符
- * @param excludePattern 要排除的路由匹配符
- * @param function 要执行的方法
- */
- public static void match(String pattern, String excludePattern, SaFunction function) {
- if(isMatchCurrURI(pattern)) {
- if(isMatchCurrURI(excludePattern) == false) {
- function.run();
- }
- }
- }
-
- /**
- * 使用路由匹配符集合与当前URI执行匹配,如果匹配成功则执行验证函数
- * @param patterns 路由匹配符集合
- * @param function 要执行的方法
- */
- public static void match(List patterns, SaFunction function) {
- if(isMatchCurrURI(patterns)) {
- function.run();
- }
- }
-
- /**
- * 使用路由匹配符集合与当前URI执行匹配 (并指定排除匹配符),如果匹配成功则执行验证函数
- * @param patterns 路由匹配符集合
- * @param excludePatterns 要排除的路由匹配符集合
- * @param function 要执行的方法
- */
- public static void match(List patterns, List excludePatterns, SaFunction function) {
- if(isMatchCurrURI(patterns)) {
- if(isMatchCurrURI(excludePatterns) == false) {
- function.run();
- }
- }
- }
-
-
- /**
- * 使用路由匹配符集合与当前URI执行匹配,如果匹配成功则执行验证函数
- * @param patterns 路由匹配符集合
- * @return 匹配结果包装对象
- */
- public static IsRunFunction match(String... patterns) {
- boolean matchResult = isMatch(Arrays.asList(patterns), SaHolder.getRequest().getRequestPath());
- return new IsRunFunction(matchResult);
- }
-
-
- // -------------------- 其它操作 --------------------
-
- /**
- * 停止匹配,跳出函数 (在多个匹配链中一次性跳出Auth函数)
- */
- public static void stop() {
- throw new StopMatchException();
- }
-
-
-
-
-}
diff --git a/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/core/application/SaApplicationTest.java b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/core/application/SaApplicationTest.java
new file mode 100644
index 00000000..5535fac7
--- /dev/null
+++ b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/core/application/SaApplicationTest.java
@@ -0,0 +1,75 @@
+package cn.dev33.satoken.core.application;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import cn.dev33.satoken.application.SaApplication;
+import cn.dev33.satoken.context.SaHolder;
+
+/**
+ * SaApplication 存取值测试
+ *
+ * @author kong
+ * @since: 2022-9-4
+ */
+public class SaApplicationTest {
+
+ // 测试
+ @Test
+ public void testSaApplication() {
+ SaApplication application = SaHolder.getApplication();
+
+ // 取值
+ application.set("age", "18");
+ Assertions.assertEquals(application.get("age").toString(), "18");
+ Assertions.assertEquals(application.getInt("age"), 18);
+ Assertions.assertEquals(application.getLong("age"), 18L);
+ Assertions.assertEquals(application.getFloat("age"), 18f);
+ Assertions.assertEquals(application.getDouble("age"), 18.0);
+ Assertions.assertEquals(application.getString("age"), "18");
+ Assertions.assertEquals(application.get("age", 20), 18);
+ Assertions.assertEquals(application.get("age2", 20), 20);
+ Assertions.assertEquals(application.getString("age2"), null);
+ // lambda 取值,有值时依然是原值
+ Assertions.assertEquals(application.get("age", () -> "23"), "18");
+ Assertions.assertEquals(application.getInt("age"), 18);
+ // lambda 取值,无值时被写入新值
+ Assertions.assertEquals(application.get("age2", () -> "23"), "23");
+ Assertions.assertEquals(application.getInt("age2"), 23);
+
+ // getModel取值
+ Assertions.assertEquals(application.getModel("age", int.class), 18);
+ Assertions.assertEquals(application.getModel("age", int.class, 30), 18);
+ Assertions.assertEquals(application.getModel("age3", int.class, 30), 30);
+
+ // 删除值
+ application.delete("age");
+ Assertions.assertNull(application.get("age"));
+
+ // 是否为空
+ Assertions.assertTrue(application.valueIsNull(null));
+ Assertions.assertTrue(application.valueIsNull(""));
+ Assertions.assertFalse(application.valueIsNull("abc"));
+
+ // 为空时才能写入
+ application.setByNull("age4", "18");
+ Assertions.assertEquals(application.getInt("age4"), 18);
+ application.setByNull("age4", "20");
+ Assertions.assertEquals(application.getInt("age4"), 18);
+
+ // 清空
+ application.clear();
+ Assertions.assertEquals(application.keys().size(), 0);
+
+ // 获取所有值
+ application.set("key1", "value1");
+ application.set("key2", "value2");
+ application.set("key3", "value3");
+ Assertions.assertEquals(application.keys().size(), 3);
+
+ // 空列表
+ application.clear();
+ Assertions.assertEquals(application.keys().size(), 0);
+ }
+
+}
diff --git a/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/core/context/model/SaCookieTest.java b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/core/context/model/SaCookieTest.java
index 1eb1fe7f..8c223cab 100644
--- a/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/core/context/model/SaCookieTest.java
+++ b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/core/context/model/SaCookieTest.java
@@ -22,8 +22,18 @@ public class SaCookieTest {
.setSameSite("Lax")
.setHttpOnly(true)
.setSecure(true);
-
+
+ Assertions.assertEquals(cookie.getName(), "satoken");
+ Assertions.assertEquals(cookie.getValue(), "xxxx-xxxx-xxxx-xxxx");
+ Assertions.assertEquals(cookie.getDomain(), "https://sa-token.dev33.cn/");
+ Assertions.assertEquals(cookie.getMaxAge(), -1);
+ Assertions.assertEquals(cookie.getPath(), "/");
+ Assertions.assertEquals(cookie.getSameSite(), "Lax");
+ Assertions.assertEquals(cookie.getHttpOnly(), true);
+ Assertions.assertEquals(cookie.getSecure(), true);
Assertions.assertEquals(cookie.toHeaderValue(), "satoken=xxxx-xxxx-xxxx-xxxx; Domain=https://sa-token.dev33.cn/; Path=/; Secure; HttpOnly; sameSite=Lax");
+
+ Assertions.assertNotNull(cookie.toString());
}
}
diff --git a/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/core/session/TokenSignTest.java b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/core/session/TokenSignTest.java
new file mode 100644
index 00000000..dec68792
--- /dev/null
+++ b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/core/session/TokenSignTest.java
@@ -0,0 +1,29 @@
+package cn.dev33.satoken.core.session;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import cn.dev33.satoken.session.TokenSign;
+
+/**
+ * TokenSign 相关测试
+ *
+ * @author kong
+ * @since: 2022-9-4
+ */
+public class TokenSignTest {
+
+ // 测试
+ @Test
+ public void testTokenSign() {
+ TokenSign tokenSign = new TokenSign();
+ tokenSign.setDevice("PC");
+ tokenSign.setValue("ttt-value");
+
+ Assertions.assertEquals(tokenSign.getDevice(), "PC");
+ Assertions.assertEquals(tokenSign.getValue(), "ttt-value");
+
+ Assertions.assertNotNull(tokenSign.toString());
+ }
+
+}
diff --git a/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/configure/HandlerException.java b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/configure/HandlerException.java
index 1072ccb3..fccf7a73 100644
--- a/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/configure/HandlerException.java
+++ b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/configure/HandlerException.java
@@ -3,6 +3,7 @@ package cn.dev33.satoken.integrate.configure;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
+import cn.dev33.satoken.exception.IdTokenInvalidException;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
@@ -40,5 +41,11 @@ public class HandlerException {
public SaResult handlerNotSafeException(NotSafeException e) {
return SaResult.error().setCode(901);
}
+
+ // id-token 校验失败,code=902
+ @ExceptionHandler(IdTokenInvalidException.class)
+ public SaResult handlerIdTokenInvalidException(IdTokenInvalidException e) {
+ return SaResult.error().setCode(902);
+ }
}
diff --git a/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/id/SaIdTokenController.java b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/id/SaIdTokenController.java
new file mode 100644
index 00000000..ca2a4e4b
--- /dev/null
+++ b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/id/SaIdTokenController.java
@@ -0,0 +1,39 @@
+package cn.dev33.satoken.integrate.id;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import cn.dev33.satoken.id.SaIdUtil;
+import cn.dev33.satoken.spring.SpringMVCUtil;
+import cn.dev33.satoken.util.SaResult;
+
+/**
+ * id-token Controller
+ *
+ * @author kong
+ *
+ */
+@RestController
+@RequestMapping("/id/")
+public class SaIdTokenController {
+
+ // 获取信息
+ @RequestMapping("getInfo")
+ public SaResult getInfo() {
+ // 获取并校验id-token
+ String idToken = SpringMVCUtil.getRequest().getHeader(SaIdUtil.ID_TOKEN);
+ SaIdUtil.checkToken(idToken);
+ // 返回信息
+ return SaResult.data("info=zhangsan");
+ }
+
+ // 获取信息2
+ @RequestMapping("getInfo2")
+ public SaResult getInfo2() {
+ // 获取并校验id-token
+ SaIdUtil.checkCurrentRequestToken();
+ // 返回信息
+ return SaResult.data("info=zhangsan2");
+ }
+
+}
diff --git a/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/id/SaIdTokenControllerTest.java b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/id/SaIdTokenControllerTest.java
new file mode 100644
index 00000000..ad9dfa86
--- /dev/null
+++ b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/id/SaIdTokenControllerTest.java
@@ -0,0 +1,130 @@
+package cn.dev33.satoken.integrate.id;
+
+import java.util.Map;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+import cn.dev33.satoken.SaManager;
+import cn.dev33.satoken.exception.IdTokenInvalidException;
+import cn.dev33.satoken.id.SaIdUtil;
+import cn.dev33.satoken.integrate.StartUpApplication;
+import cn.dev33.satoken.util.SaResult;
+
+/**
+ * id-token Controller 测试
+ *
+ * @author kong
+ *
+ */
+@SpringBootTest(classes = StartUpApplication.class)
+public class SaIdTokenControllerTest {
+
+ @Autowired
+ private WebApplicationContext wac;
+
+ private MockMvc mvc;
+
+ // 开始
+ @BeforeEach
+ public void before() {
+ mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+ }
+
+ // 获取信息
+ @Test
+ public void testGetInfo() {
+ String token = SaIdUtil.getToken();
+ // 加token,能调通
+ SaResult res = request("/id/getInfo", token);
+ Assertions.assertEquals(res.getCode(), 200);
+ // 不加token,不能调通
+ SaResult res2 = request("/id/getInfo", "xxx");
+ Assertions.assertEquals(res2.getCode(), 902);
+
+ // 获取信息2
+ token = SaIdUtil.getTokenNh();
+ // 加token,能调通
+ SaResult res3 = request("/id/getInfo2", token);
+ Assertions.assertEquals(res3.getCode(), 200);
+ // 不加token,不能调通
+ SaResult res4 = request("/id/getInfo2", "xxx");
+ Assertions.assertEquals(res4.getCode(), 902);
+ }
+
+ // 基础测试
+ @Test
+ public void testApi() {
+ String token = SaIdUtil.getToken();
+
+ // 刷新一下,会有变化
+ SaIdUtil.refreshToken();
+ String token2 = SaIdUtil.getToken();
+ Assertions.assertNotEquals(token, token2);
+
+ // 旧token,变为次级token
+ String pastToken = SaIdUtil.getPastTokenNh();
+ Assertions.assertEquals(token, pastToken);
+
+ // dao中应该有值
+ String daoToken = SaManager.getSaTokenDao().get("satoken:var:id-token");
+ String daoToken2 = SaManager.getSaTokenDao().get("satoken:var:past-id-token");
+ Assertions.assertEquals(token2, daoToken);
+ Assertions.assertEquals(token, daoToken2);
+
+ // 新旧都有效
+ Assertions.assertTrue(SaIdUtil.isValid(token));
+ Assertions.assertTrue(SaIdUtil.isValid(token2));
+
+ // 空的不行
+ Assertions.assertFalse(SaIdUtil.isValid(null));
+ Assertions.assertFalse(SaIdUtil.isValid(""));
+
+ // 不抛出异常
+ Assertions.assertDoesNotThrow(() -> SaIdUtil.checkToken(token));
+ Assertions.assertDoesNotThrow(() -> SaIdUtil.checkToken(token2));
+
+ // 抛出异常
+ Assertions.assertThrows(IdTokenInvalidException.class, () -> SaIdUtil.checkToken(null));
+ Assertions.assertThrows(IdTokenInvalidException.class, () -> SaIdUtil.checkToken(""));
+ Assertions.assertThrows(IdTokenInvalidException.class, () -> SaIdUtil.checkToken("aaa"));
+ }
+
+
+
+ // 封装请求
+ private SaResult request(String path, String idToken) {
+ try {
+ // 发请求
+ MvcResult mvcResult = mvc.perform(
+ MockMvcRequestBuilders.post(path)
+ .contentType(MediaType.APPLICATION_PROBLEM_JSON)
+ .accept(MediaType.APPLICATION_PROBLEM_JSON)
+ .header(SaIdUtil.ID_TOKEN, idToken)
+ )
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andReturn();
+
+ // 转 Map
+ String content = mvcResult.getResponse().getContentAsString();
+ Map map = SaManager.getSaJsonTemplate().parseJsonToMap(content);
+
+ // 转 SaResult 对象
+ return new SaResult().setMap(map);
+
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/login/LoginControllerTest.java b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/login/LoginControllerTest.java
index f57d7c0b..27c102be 100644
--- a/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/login/LoginControllerTest.java
+++ b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/login/LoginControllerTest.java
@@ -21,7 +21,7 @@ import cn.dev33.satoken.util.SoMap;
/**
* Sa-Token 登录API测试
*
- * @author Auster
+ * @author kong
*
*/
@SpringBootTest(classes = StartUpApplication.class)
@@ -95,8 +95,8 @@ public class LoginControllerTest {
private SoMap request(String path) throws Exception {
MvcResult mvcResult = mvc.perform(
MockMvcRequestBuilders.post(path)
- .contentType(MediaType.APPLICATION_JSON_UTF8)
- .accept(MediaType.APPLICATION_JSON_UTF8)
+ .contentType(MediaType.APPLICATION_PROBLEM_JSON)
+ .accept(MediaType.APPLICATION_PROBLEM_JSON)
)
.andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();
diff --git a/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/more/MoreController.java b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/more/MoreController.java
new file mode 100644
index 00000000..ea3fd084
--- /dev/null
+++ b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/more/MoreController.java
@@ -0,0 +1,40 @@
+package cn.dev33.satoken.integrate.more;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import cn.dev33.satoken.context.SaHolder;
+import cn.dev33.satoken.context.model.SaRequest;
+import cn.dev33.satoken.util.SaFoxUtil;
+import cn.dev33.satoken.util.SaResult;
+
+/**
+ * 其它测试
+ *
+ * @author kong
+ *
+ */
+@RestController
+@RequestMapping("/more/")
+public class MoreController {
+
+ // 一些基本的测试
+ @RequestMapping("getInfo")
+ public SaResult getInfo() {
+ SaRequest req = SaHolder.getRequest();
+ boolean flag =
+ SaFoxUtil.equals(req.getParam("name"), "zhang")
+ && SaFoxUtil.equals(req.getParam("name2", "li"), "li")
+ && SaFoxUtil.equals(req.getParamNotNull("name"), "zhang")
+ && req.isParam("name", "zhang")
+ && req.isPath("/more/getInfo")
+ && req.hasParam("name")
+ && SaFoxUtil.equals(req.getHeader("div"), "val")
+ && SaFoxUtil.equals(req.getHeader("div", "zhang"), "val")
+ && SaFoxUtil.equals(req.getHeader("div2", "zhang"), "zhang")
+ ;
+
+ return SaResult.data(flag);
+ }
+
+}
diff --git a/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/more/MoreControllerTest.java b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/more/MoreControllerTest.java
new file mode 100644
index 00000000..1a3e29cc
--- /dev/null
+++ b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/more/MoreControllerTest.java
@@ -0,0 +1,97 @@
+package cn.dev33.satoken.integrate.more;
+
+import java.util.Map;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+import cn.dev33.satoken.SaManager;
+import cn.dev33.satoken.context.model.SaRequest;
+import cn.dev33.satoken.integrate.StartUpApplication;
+import cn.dev33.satoken.servlet.model.SaRequestForServlet;
+import cn.dev33.satoken.spring.SaTokenContextForSpring;
+import cn.dev33.satoken.spring.SpringMVCUtil;
+import cn.dev33.satoken.util.SaResult;
+
+
+/**
+ * 其它测试
+ *
+ * @author kong
+ *
+ */
+@SpringBootTest(classes = StartUpApplication.class)
+public class MoreControllerTest {
+
+ @Autowired
+ private WebApplicationContext wac;
+
+ private MockMvc mvc;
+
+ // 开始
+ @BeforeEach
+ public void before() {
+ mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+
+ // 在单元测试时,通过 request.getServletPath() 获取到的请求路径为空,导致路由拦截不正确
+ // 虽然不知道为什么会这样,但是暂时可以通过以下方式来解决
+ SaManager.setSaTokenContext(new SaTokenContextForSpring() {
+ @Override
+ public SaRequest getRequest() {
+ return new SaRequestForServlet(SpringMVCUtil.getRequest()) {
+ @Override
+ public String getRequestPath() {
+ return request.getRequestURI();
+ }
+ };
+ }
+ });
+
+ }
+
+ // 基础API测试
+ @Test
+ public void testApi() {
+ SaResult res = request("/more/getInfo?name=zhang");
+ Assertions.assertEquals(res.getData(), true);
+
+
+ }
+
+
+ // 封装请求
+ private SaResult request(String path) {
+ try {
+ // 发请求
+ MvcResult mvcResult = mvc.perform(
+ MockMvcRequestBuilders.post(path)
+ .contentType(MediaType.APPLICATION_PROBLEM_JSON)
+ .accept(MediaType.APPLICATION_PROBLEM_JSON)
+ .header("div", "val")
+ )
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andReturn();
+
+ // 转 Map
+ String content = mvcResult.getResponse().getContentAsString();
+ Map map = SaManager.getSaJsonTemplate().parseJsonToMap(content);
+
+ // 转 SaResult 对象
+ return new SaResult().setMap(map);
+
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/router/RouterController.java b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/router/RouterController.java
new file mode 100644
index 00000000..3941b087
--- /dev/null
+++ b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/router/RouterController.java
@@ -0,0 +1,28 @@
+package cn.dev33.satoken.integrate.router;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import cn.dev33.satoken.util.SaResult;
+
+/**
+ * 路由鉴权测试
+ *
+ * @author kong
+ *
+ */
+@RestController
+@RequestMapping("/rt/")
+public class RouterController {
+
+ @RequestMapping("getInfo")
+ public SaResult getInfo() {
+ return SaResult.ok();
+ }
+
+ @RequestMapping("getInfo*")
+ public SaResult getInfo2() {
+ return SaResult.ok();
+ }
+
+}
diff --git a/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/router/RouterControllerTest.java b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/router/RouterControllerTest.java
new file mode 100644
index 00000000..bd3a944a
--- /dev/null
+++ b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/router/RouterControllerTest.java
@@ -0,0 +1,179 @@
+package cn.dev33.satoken.integrate.router;
+
+import java.util.Arrays;
+import java.util.Map;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+import cn.dev33.satoken.SaManager;
+import cn.dev33.satoken.context.model.SaRequest;
+import cn.dev33.satoken.integrate.StartUpApplication;
+import cn.dev33.satoken.router.SaRouter;
+import cn.dev33.satoken.router.SaRouterStaff;
+import cn.dev33.satoken.servlet.model.SaRequestForServlet;
+import cn.dev33.satoken.spring.SaTokenContextForSpring;
+import cn.dev33.satoken.spring.SpringMVCUtil;
+import cn.dev33.satoken.util.SaResult;
+
+
+/**
+ * C Controller 测试
+ *
+ * @author kong
+ *
+ */
+@SpringBootTest(classes = StartUpApplication.class)
+public class RouterControllerTest {
+
+ @Autowired
+ private WebApplicationContext wac;
+
+ private MockMvc mvc;
+
+ // 开始
+ @BeforeEach
+ public void before() {
+ mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+
+ // 在单元测试时,通过 request.getServletPath() 获取到的请求路径为空,导致路由拦截不正确
+ // 虽然不知道为什么会这样,但是暂时可以通过以下方式来解决
+ SaManager.setSaTokenContext(new SaTokenContextForSpring() {
+ @Override
+ public SaRequest getRequest() {
+ return new SaRequestForServlet(SpringMVCUtil.getRequest()) {
+ @Override
+ public String getRequestPath() {
+ return request.getRequestURI();
+ }
+ };
+ }
+ });
+
+ }
+
+ // 基础API测试
+ @Test
+ public void testApi() {
+ // 是否命中
+ SaRouterStaff staff = SaRouter.match(false);
+ Assertions.assertFalse(staff.isHit());
+
+ // 重置
+ staff.reset();
+ Assertions.assertTrue(staff.isHit());
+
+ // lambda 形式
+ SaRouterStaff staff2 = SaRouter.match(r -> false);
+ Assertions.assertFalse(staff2.isHit());
+
+ // 匹配
+ Assertions.assertTrue(SaRouter.isMatch("/user/**", "/user/add"));
+ Assertions.assertTrue(SaRouter.isMatch(new String[] {"/user/**", "/art/**", "/goods/**"}, "/art/delete"));
+ Assertions.assertTrue(SaRouter.isMatch(Arrays.asList("/user/**", "/art/**", "/goods/**"), "/art/delete"));
+ Assertions.assertTrue(SaRouter.isMatch(new String[] {"POST", "GET", "PUT"}, "GET"));
+
+ // 不匹配的
+ Assertions.assertTrue(SaRouter.notMatch(false).isHit());
+ Assertions.assertTrue(SaRouter.notMatch(r -> false).isHit());
+ }
+
+ @Test
+ public void testRouter() {
+ // getInfo
+ SaResult res = request("/rt/getInfo?name=zhang");
+ Assertions.assertEquals(res.getCode(), 201);
+
+ // getInfo2
+ SaResult res2 = request("/rt/getInfo2");
+ Assertions.assertEquals(res2.getCode(), 202);
+
+ // getInfo3
+ SaResult res3 = request("/rt/getInfo3");
+ Assertions.assertEquals(res3.getCode(), 203);
+
+ // getInfo4
+ SaResult res4 = request("/rt/getInfo4");
+ Assertions.assertEquals(res4.getCode(), 204);
+
+ // getInfo5
+ SaResult res5 = request("/rt/getInfo5");
+ Assertions.assertEquals(res5.getCode(), 205);
+
+ // getInfo6
+ SaResult res6 = request("/rt/getInfo6");
+ Assertions.assertEquals(res6.getCode(), 206);
+
+ // getInfo7
+ SaResult res7 = request("/rt/getInfo7");
+ Assertions.assertEquals(res7.getCode(), 200);
+
+ // getInfo8
+ SaResult res8 = request("/rt/getInfo8");
+ Assertions.assertEquals(res8.getCode(), 200);
+
+ // getInfo9
+ SaResult res9 = request("/rt/getInfo9");
+ Assertions.assertEquals(res9.getCode(), 209);
+
+ // getInfo10
+ SaResult res10 = request("/rt/getInfo10");
+ Assertions.assertEquals(res10.getCode(), 200);
+
+ // getInfo11
+ SaResult res11 = request("/rt/getInfo11");
+ Assertions.assertEquals(res11.getCode(), 211);
+
+ // getInfo12
+ SaResult res12 = request("/rt/getInfo12");
+ Assertions.assertEquals(res12.getCode(), 212);
+
+ // getInfo13
+ SaResult res13 = request("/rt/getInfo13");
+ Assertions.assertEquals(res13.getCode(), 213);
+
+ // getInfo14
+ SaResult res14 = request("/rt/getInfo14");
+ Assertions.assertEquals(res14.getCode(), 214);
+
+ // getInfo15
+ SaResult res15 = request("/rt/getInfo15");
+ Assertions.assertEquals(res15.getCode(), 215);
+ }
+
+
+ // 封装请求
+ private SaResult request(String path) {
+ try {
+ // 发请求
+ MvcResult mvcResult = mvc.perform(
+ MockMvcRequestBuilders.post(path)
+ .contentType(MediaType.APPLICATION_PROBLEM_JSON)
+ .accept(MediaType.APPLICATION_PROBLEM_JSON)
+ )
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andReturn();
+
+ // 转 Map
+ String content = mvcResult.getResponse().getContentAsString();
+ Map map = SaManager.getSaJsonTemplate().parseJsonToMap(content);
+
+ // 转 SaResult 对象
+ return new SaResult().setMap(map);
+
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/router/SaTokenConfigure2.java b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/router/SaTokenConfigure2.java
new file mode 100644
index 00000000..4c517ec6
--- /dev/null
+++ b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/router/SaTokenConfigure2.java
@@ -0,0 +1,79 @@
+package cn.dev33.satoken.integrate.router;
+
+import java.util.Arrays;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import cn.dev33.satoken.context.SaHolder;
+import cn.dev33.satoken.interceptor.SaInterceptor;
+import cn.dev33.satoken.router.SaHttpMethod;
+import cn.dev33.satoken.router.SaRouter;
+import cn.dev33.satoken.util.SaResult;
+
+/**
+ * Sa-Token 相关配置类
+ *
+ * @author kong
+ * @since: 2022-9-2
+ */
+@Configuration
+public class SaTokenConfigure2 implements WebMvcConfigurer {
+
+ // 路由鉴权
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 路由鉴权
+ registry.addInterceptor(new SaInterceptor(handle -> {
+
+ // 匹配 getInfo ,返回code=201
+ SaRouter.match("/**")
+ .match(SaHttpMethod.POST)
+ .matchMethod("POST")
+ .match(SaHolder.getRequest().getMethod().equals("POST"))
+ .match(r -> SaHolder.getRequest().isPath("/rt/getInfo"))
+ .match(r -> SaHolder.getRequest().isParam("name", "zhang"))
+ .back(SaResult.code(201));
+
+ // 匹配 getInfo2 ,返回code=202
+ SaRouter.match("/rt/getInfo2")
+ .match(Arrays.asList("/rt/getInfo2", "/rt/*"))
+ .notMatch("/rt/getInfo3")
+ .notMatch(false)
+ .notMatch(r -> false)
+ .notMatch(SaHttpMethod.GET)
+ .notMatchMethod("PUT")
+ .notMatch(Arrays.asList("/rt/getInfo4", "/rt/getInfo5"))
+ .back(SaResult.code(202));
+
+ // 匹配 getInfo3 ,返回code=203
+ SaRouter.match("/rt/getInfo3", "/rt/getInfo4", () -> SaRouter.back(SaResult.code(203)));
+ SaRouter.match("/rt/getInfo4", "/rt/getInfo5", r -> SaRouter.back(SaResult.code(204)));
+ SaRouter.match("/rt/getInfo5", () -> SaRouter.back(SaResult.code(205)));
+ SaRouter.match("/rt/getInfo6", r -> SaRouter.back(SaResult.code(206)));
+
+ // 通往 Controller
+ SaRouter.match(Arrays.asList("/rt/getInfo7")).stop();
+
+ // 通往 Controller
+ SaRouter.match("/rt/getInfo8", () -> SaRouter.stop());
+
+ SaRouter.matchMethod("POST").match("/rt/getInfo9").free(r -> SaRouter.back(SaResult.code(209)));
+ SaRouter.match(SaHttpMethod.POST).match("/rt/getInfo10").setHit(false).back();
+
+ // 11
+ SaRouter.notMatch("/rt/getInfo11").reset().match("/rt/getInfo11").back(SaResult.code(211));
+ SaRouter.notMatch(SaHttpMethod.GET).match("/rt/getInfo12").back(SaResult.code(212));
+ SaRouter.notMatch(Arrays.asList("/rt/getInfo12", "/rt/getInfo14")).match("/rt/getInfo13").back(SaResult.code(213));
+ SaRouter.notMatchMethod("GET", "PUT").match("/rt/getInfo14").back(SaResult.code(214));
+
+// SaRouter.match(Arrays.asList("/rt/getInfo15", "/rt/getInfo16"))
+ if(SaRouter.isMatchCurrURI("/rt/getInfo15")) {
+ SaRouter.newMatch().free(r -> SaRouter.back(SaResult.code(215)));
+ }
+
+ })).addPathPatterns("/**");
+ }
+}
+