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("/**"); + } +} +