diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/exception/ApiDisabledException.java b/sa-token-core/src/main/java/cn/dev33/satoken/exception/ApiDisabledException.java new file mode 100644 index 00000000..a4779fd2 --- /dev/null +++ b/sa-token-core/src/main/java/cn/dev33/satoken/exception/ApiDisabledException.java @@ -0,0 +1,31 @@ +package cn.dev33.satoken.exception; + +/** + * 一个异常:代表 API 已被禁用 + * @author kong + */ +public class ApiDisabledException extends SaTokenException { + + /** + * 序列化版本号 + */ + private static final long serialVersionUID = 6806129545290130133L; + + /** 异常提示语 */ + public static final String BE_MESSAGE = "This API is disabled"; + + /** + * 一个异常:代表 API 已被禁用 + */ + public ApiDisabledException() { + super(BE_MESSAGE); + } + + /** + * 一个异常:代表 API 已被禁用 + * @param message 异常描述 + */ + public ApiDisabledException(String message) { + super(message); + } +} diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java b/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java index 661b5505..d9437494 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java @@ -84,14 +84,16 @@ public class StpLogic { } /** - * 创建一个TokenValue - * @param loginId loginId + * 创建一个TokenValue + * @param loginId loginId + * @param device 设备标识 + * @param timeout 过期时间 * @return 生成的tokenValue */ - public String createTokenValue(Object loginId) { + public String createTokenValue(Object loginId, String device, long timeout) { return SaStrategy.me.createToken.apply(loginId, loginType); } - + /** * 在当前会话写入当前TokenValue * @param tokenValue token值 @@ -255,7 +257,7 @@ public class StpLogic { // --- 如果允许并发登录 if(config.getIsConcurrent()) { // 如果配置为共享token, 则尝试从Session签名记录里取出token - if(config.getIsShare()) { + if(getConfigOfIsShare()) { tokenValue = getTokenValueByLoginId(id, loginModel.getDeviceOrDefault()); } } else { @@ -264,7 +266,7 @@ public class StpLogic { } // 如果至此,仍未成功创建tokenValue, 则开始生成一个 if(tokenValue == null) { - tokenValue = createTokenValue(id); + tokenValue = createTokenValue(id, loginModel.getDeviceOrDefault(), loginModel.getTimeout()); } // ------ 3. 获取 User-Session , 续期 @@ -767,7 +769,7 @@ public class StpLogic { String tokenValue = getTokenValue(); if(tokenValue == null || Objects.equals(tokenValue, "")) { // 随机一个token送给Ta - tokenValue = createTokenValue(null); + tokenValue = createTokenValue(null, null, getConfig().getTimeout()); // 写入 [最后操作时间] setLastActivityToNow(tokenValue); // 在当前会话写入这个tokenValue @@ -1621,6 +1623,14 @@ public class StpLogic { return SaManager.getConfig(); } + /** + * 返回全局配置对象的isShare属性 + * @return / + */ + public boolean getConfigOfIsShare() { + return getConfig().getIsShare(); + } + /** * 返回持久化对象 * @return / diff --git a/sa-token-demo/sa-token-demo-jwt/src/main/java/com/pj/satoken/SaTokenConfigure.java b/sa-token-demo/sa-token-demo-jwt/src/main/java/com/pj/satoken/SaTokenConfigure.java index 5aae843f..1499835a 100644 --- a/sa-token-demo/sa-token-demo-jwt/src/main/java/com/pj/satoken/SaTokenConfigure.java +++ b/sa-token-demo/sa-token-demo-jwt/src/main/java/com/pj/satoken/SaTokenConfigure.java @@ -6,7 +6,7 @@ import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import cn.dev33.satoken.interceptor.SaAnnotationInterceptor; -import cn.dev33.satoken.jwt.StpLogicJwtForStateless; +import cn.dev33.satoken.jwt.StpLogicJwtForTokenStyle; import cn.dev33.satoken.stp.StpLogic; @@ -32,7 +32,7 @@ public class SaTokenConfigure implements WebMvcConfigurer { */ @Bean public StpLogic getStpLogicJwt() { - return new StpLogicJwtForStateless(); + return new StpLogicJwtForTokenStyle(); } } diff --git a/sa-token-demo/sa-token-demo-jwt/src/test/java/com/pj/test/JwtForMixTest.java b/sa-token-demo/sa-token-demo-jwt/src/test/java/com/pj/test/JwtForMixTest.java new file mode 100644 index 00000000..55ef7429 --- /dev/null +++ b/sa-token-demo/sa-token-demo-jwt/src/test/java/com/pj/test/JwtForMixTest.java @@ -0,0 +1,256 @@ +package com.pj.test; + +import java.util.List; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import cn.dev33.satoken.SaManager; +import cn.dev33.satoken.dao.SaTokenDao; +import cn.dev33.satoken.exception.ApiDisabledException; +import cn.dev33.satoken.exception.DisableLoginException; +import cn.dev33.satoken.jwt.SaJwtUtil; +import cn.dev33.satoken.jwt.StpLogicJwtForMix; +import cn.dev33.satoken.session.SaSession; +import cn.dev33.satoken.stp.StpUtil; +import cn.dev33.satoken.util.SaTokenConsts; +import cn.hutool.json.JSONObject; +import cn.hutool.jwt.JWT; + +/** + * Sa-Token 整合 jwt:mix 模式 测试 + * + * @author kong + * + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = StartUpApplication.class) +public class JwtForMixTest { + + // 持久化Bean + @Autowired(required = false) + SaTokenDao dao = SaManager.getSaTokenDao(); + + // 开始 + @BeforeClass + public static void beforeClass() { + System.out.println("\n\n------------------------ JwtForMixTest star ..."); + StpUtil.setStpLogic(new StpLogicJwtForMix()); + } + + // 结束 + @AfterClass + public static void afterClass() { + System.out.println("\n\n------------------------ JwtForMixTest end ... \n"); + } + + // 测试:登录 + @Test + public void doLogin() { + // 登录 + StpUtil.login(10001); + String token = StpUtil.getTokenValue(); + + // API 验证 + Assert.assertTrue(StpUtil.isLogin()); + Assert.assertNotNull(token); // token不为null + Assert.assertEquals(StpUtil.getLoginIdAsLong(), 10001); // loginId=10001 + Assert.assertEquals(StpUtil.getLoginDevice(), SaTokenConsts.DEFAULT_LOGIN_DEVICE); // 登录设备 + + // token 验证 + JWT jwt = JWT.of(token); + JSONObject payloads = jwt.getPayloads(); + Assert.assertEquals(payloads.getStr(SaJwtUtil.LOGIN_ID), "10001"); // 账号 + Assert.assertEquals(payloads.getStr(SaJwtUtil.DEVICE), SaTokenConsts.DEFAULT_LOGIN_DEVICE); // 登录设备 + Assert.assertEquals(payloads.getStr(SaJwtUtil.LOGIN_TYPE), StpUtil.TYPE); // 账号类型 + + // db数据 验证 + // token不存在 + Assert.assertNull(dao.get("satoken:login:token:" + token)); + // Session 存在 + SaSession session = dao.getSession("satoken:login:session:" + 10001); + Assert.assertNotNull(session); + Assert.assertEquals(session.getId(), "satoken:login:session:" + 10001); + Assert.assertTrue(session.getTokenSignList().size() >= 1); + } + + // 测试:注销 + @Test + public void logout() { + // 登录 + StpUtil.login(10001); + String token = StpUtil.getTokenValue(); + Assert.assertEquals(JWT.of(token).getPayloads().getStr("loginId"), "10001"); + + // 注销 + StpUtil.logout(); + // token 应该被清除 + Assert.assertNull(StpUtil.getTokenValue()); + Assert.assertFalse(StpUtil.isLogin()); + } + + // 测试:Session会话 + @Test + public void testSession() { + StpUtil.login(10001); + + // API 应该可以获取 Session + Assert.assertNotNull(StpUtil.getSession(false)); + + // db中应该存在 Session + SaSession session = dao.getSession("satoken:login:session:" + 10001); + Assert.assertNotNull(session); + + // 存取值 + session.set("name", "zhang"); + session.set("age", "18"); + Assert.assertEquals(session.get("name"), "zhang"); + Assert.assertEquals(session.getInt("age"), 18); + Assert.assertEquals((int)session.getModel("age", int.class), 18); + Assert.assertEquals((int)session.get("age", 20), 18); + Assert.assertEquals((int)session.get("name2", 20), 20); + Assert.assertEquals((int)session.get("name2", () -> 30), 30); + session.clear(); + Assert.assertEquals(session.get("name"), null); + } + + // 测试:权限认证 + @Test + public void testCheckPermission() { + StpUtil.login(10001); + + // 权限认证 + Assert.assertTrue(StpUtil.hasPermission("user-add")); + Assert.assertTrue(StpUtil.hasPermission("user-list")); + Assert.assertTrue(StpUtil.hasPermission("user")); + Assert.assertTrue(StpUtil.hasPermission("art-add")); + Assert.assertFalse(StpUtil.hasPermission("get-user")); + // and + Assert.assertTrue(StpUtil.hasPermissionAnd("art-add", "art-get")); + Assert.assertFalse(StpUtil.hasPermissionAnd("art-add", "comment-add")); + // or + Assert.assertTrue(StpUtil.hasPermissionOr("art-add", "comment-add")); + Assert.assertFalse(StpUtil.hasPermissionOr("comment-add", "comment-delete")); + } + + // 测试:角色认证 + @Test + public void testCheckRole() { + StpUtil.login(10001); + + // 角色认证 + Assert.assertTrue(StpUtil.hasRole("admin")); + Assert.assertFalse(StpUtil.hasRole("teacher")); + // and + Assert.assertTrue(StpUtil.hasRoleAnd("admin", "super-admin")); + Assert.assertFalse(StpUtil.hasRoleAnd("admin", "ceo")); + // or + Assert.assertTrue(StpUtil.hasRoleOr("admin", "ceo")); + Assert.assertFalse(StpUtil.hasRoleOr("ceo", "cto")); + } + + // 测试:根据token强制注销 + @Test(expected = ApiDisabledException.class) + public void testLogoutByToken() { + + // 先登录上 + StpUtil.login(10001); + Assert.assertTrue(StpUtil.isLogin()); + String token = StpUtil.getTokenValue(); + + // 根据token注销 + StpUtil.logoutByTokenValue(token); + } + + // 测试:根据账号id强制注销 + @Test(expected = ApiDisabledException.class) + public void testLogoutByLoginId() { + + // 先登录上 + StpUtil.login(10001); + Assert.assertTrue(StpUtil.isLogin()); + + // 根据账号id注销 + StpUtil.logout(10001); + } + + // 测试Token-Session + @Test + public void testTokenSession() { + + // 先登录上 + StpUtil.login(10001); + String token = StpUtil.getTokenValue(); + + // 刚开始不存在 + Assert.assertNull(StpUtil.stpLogic.getTokenSession(false)); + SaSession session = dao.getSession("satoken:login:token-session:" + token); + Assert.assertNull(session); + + // 调用一次就存在了 + StpUtil.getTokenSession(); + Assert.assertNotNull(StpUtil.stpLogic.getTokenSession(false)); + SaSession session2 = dao.getSession("satoken:login:token-session:" + token); + Assert.assertNotNull(session2); + } + + // 测试:账号封禁 + @Test(expected = DisableLoginException.class) + public void testDisable() { + + // 封号 + StpUtil.disable(10007, 200); + Assert.assertTrue(StpUtil.isDisable(10007)); + Assert.assertEquals(dao.get("satoken:login:disable:" + 10007), DisableLoginException.BE_VALUE); + + // 解封 + StpUtil.untieDisable(10007); + Assert.assertFalse(StpUtil.isDisable(10007)); + Assert.assertEquals(dao.get("satoken:login:disable:" + 10007), null); + + // 封号后登陆 (会抛出 DisableLoginException 异常) + StpUtil.disable(10007, 200); + StpUtil.login(10007); + } + + // 测试:身份切换 + @Test + public void testSwitch() { + // 登录 + StpUtil.login(10001); + Assert.assertFalse(StpUtil.isSwitch()); + Assert.assertEquals(StpUtil.getLoginIdAsLong(), 10001); + + // 开始身份切换 + StpUtil.switchTo(10044); + Assert.assertTrue(StpUtil.isSwitch()); + Assert.assertEquals(StpUtil.getLoginIdAsLong(), 10044); + + // 结束切换 + StpUtil.endSwitch(); + Assert.assertFalse(StpUtil.isSwitch()); + Assert.assertEquals(StpUtil.getLoginIdAsLong(), 10001); + } + + // 测试:会话管理 + @Test(expected = ApiDisabledException.class) + public void testSearchTokenValue() { + // 登录 + StpUtil.login(10001); + StpUtil.login(10002); + StpUtil.login(10003); + StpUtil.login(10004); + StpUtil.login(10005); + + // 查询 + List list = StpUtil.searchTokenValue("", 0, 10); + Assert.assertTrue(list.size() >= 5); + } + +} diff --git a/sa-token-demo/sa-token-demo-jwt/src/test/java/com/pj/test/JwtForStatelessTest.java b/sa-token-demo/sa-token-demo-jwt/src/test/java/com/pj/test/JwtForStatelessTest.java index 36c02fc3..07be7727 100644 --- a/sa-token-demo/sa-token-demo-jwt/src/test/java/com/pj/test/JwtForStatelessTest.java +++ b/sa-token-demo/sa-token-demo-jwt/src/test/java/com/pj/test/JwtForStatelessTest.java @@ -5,12 +5,13 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import cn.dev33.satoken.SaManager; import cn.dev33.satoken.dao.SaTokenDao; -import cn.dev33.satoken.exception.SaTokenException; +import cn.dev33.satoken.exception.ApiDisabledException; import cn.dev33.satoken.jwt.SaJwtUtil; import cn.dev33.satoken.jwt.StpLogicJwtForStateless; import cn.dev33.satoken.stp.StpUtil; @@ -21,7 +22,6 @@ import cn.hutool.jwt.JWT; /** * Sa-Token 整合 jwt:stateless 模式 测试 * - * * @author kong * */ @@ -30,20 +30,20 @@ import cn.hutool.jwt.JWT; public class JwtForStatelessTest { // 持久化Bean - static SaTokenDao dao; + @Autowired(required = false) + SaTokenDao dao = SaManager.getSaTokenDao(); // 开始 @BeforeClass public static void beforeClass() { - System.out.println("\n\n------------------------ 基础测试 star ..."); - dao = SaManager.getSaTokenDao(); + System.out.println("\n\n------------------------ JwtForStatelessTest star ..."); StpUtil.setStpLogic(new StpLogicJwtForStateless()); } // 结束 @AfterClass public static void afterClass() { - System.out.println("\n\n------------------------ 基础测试 end ... \n"); + System.out.println("\n\n------------------------ JwtForStatelessTest end ... \n"); } // 测试:登录 @@ -95,7 +95,7 @@ public class JwtForStatelessTest { } // 测试:Session会话 - @Test(expected = SaTokenException.class) + @Test(expected = ApiDisabledException.class) public void testSession() { StpUtil.login(10001); @@ -139,7 +139,7 @@ public class JwtForStatelessTest { } // 测试:根据token强制注销 - @Test(expected = SaTokenException.class) + @Test(expected = ApiDisabledException.class) public void testLogoutByToken() { // 先登录上 @@ -152,7 +152,7 @@ public class JwtForStatelessTest { } // 测试:根据账号id强制注销 - @Test(expected = SaTokenException.class) + @Test(expected = ApiDisabledException.class) public void testLogoutByLoginId() { // 先登录上 diff --git a/sa-token-doc/index.html b/sa-token-doc/index.html index 7ef57cd8..42021908 100644 --- a/sa-token-doc/index.html +++ b/sa-token-doc/index.html @@ -257,6 +257,9 @@ + + +
diff --git a/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForMix.java b/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForMix.java new file mode 100644 index 00000000..196a525b --- /dev/null +++ b/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForMix.java @@ -0,0 +1,209 @@ +package cn.dev33.satoken.jwt; + +import java.util.List; + +import cn.dev33.satoken.context.SaHolder; +import cn.dev33.satoken.dao.SaTokenDao; +import cn.dev33.satoken.exception.ApiDisabledException; +import cn.dev33.satoken.exception.NotLoginException; +import cn.dev33.satoken.stp.SaTokenInfo; +import cn.dev33.satoken.stp.StpLogic; +import cn.dev33.satoken.stp.StpUtil; + +/** + * Sa-Token 整合 jwt -- Mix 混入 + * @author kong + * + */ +public class StpLogicJwtForMix extends StpLogic { + + /** + * Sa-Token 整合 jwt -- Mix 混入 + */ + public StpLogicJwtForMix() { + super(StpUtil.TYPE); + } + + /** + * Sa-Token 整合 jwt -- Mix 混入 + * @param loginType 账号体系标识 + */ + public StpLogicJwtForMix(String loginType) { + super(loginType); + } + + /** + * 获取jwt秘钥 + * @return / + */ + public String jwtSecretKey() { + return getConfig().getJwtSecretKey(); + } + + // + // ------ 重写方法 + // + + // ------------------- 获取token 相关 ------------------- + + /** + * 创建一个TokenValue + */ + @Override + public String createTokenValue(Object loginId, String device, long timeout) { + return SaJwtUtil.createToken(loginType, loginId, device, timeout, jwtSecretKey()); + } + + /** + * 获取当前会话的Token信息 + * @return token信息 + */ + @Override + public SaTokenInfo getTokenInfo() { + SaTokenInfo info = new SaTokenInfo(); + info.tokenName = getTokenName(); + info.tokenValue = getTokenValue(); + info.isLogin = isLogin(); + info.loginId = getLoginIdDefaultNull(); + info.loginType = getLoginType(); + info.tokenTimeout = getTokenTimeout(); + info.sessionTimeout = SaTokenDao.NOT_VALUE_EXPIRE; + info.tokenSessionTimeout = SaTokenDao.NOT_VALUE_EXPIRE; + info.tokenActivityTimeout = SaTokenDao.NOT_VALUE_EXPIRE; + info.loginDevice = getLoginDevice(); + return info; + } + + // ------------------- 登录相关操作 ------------------- + + /** + * 获取指定Token对应的账号id (不做任何特殊处理) + */ + @Override + public String getLoginIdNotHandle(String tokenValue) { + // 先验证 loginType,如果不符,则视为无效token,返回null + String loginType = SaJwtUtil.getPayloadsNotCheck(tokenValue, jwtSecretKey()).getStr(SaJwtUtil.LOGIN_TYPE); + if(getLoginType().equals(loginType) == false) { + return null; + } + // 获取 loginId + try { + Object loginId = SaJwtUtil.getLoginId(tokenValue, jwtSecretKey()); + return String.valueOf(loginId); + } catch (NotLoginException e) { + return null; + } + } + + /** + * 会话注销 + */ + @Override + public void logout() { + // ... + + // 从当前 [storage存储器] 里删除 + SaHolder.getStorage().delete(splicingKeyJustCreatedSave()); + + // 如果打开了Cookie模式,则把cookie清除掉 + if(getConfig().getIsReadCookie()){ + SaHolder.getResponse().deleteCookie(getTokenName()); + } + } + + /** + * [禁用] 会话注销,根据账号id 和 设备标识 + */ + @Override + public void logout(Object loginId, String device) { + throw new ApiDisabledException(); + } + + /** + * [禁用] 会话注销,根据指定 Token + */ + @Override + public void logoutByTokenValue(String tokenValue) { + throw new ApiDisabledException(); + } + + /** + * [禁用] 踢人下线,根据账号id 和 设备标识 + */ + @Override + public void kickout(Object loginId, String device) { + throw new ApiDisabledException(); + } + + /** + * [禁用] 踢人下线,根据指定 Token + */ + @Override + public void kickoutByTokenValue(String tokenValue) { + throw new ApiDisabledException(); + } + + /** + * [禁用] 顶人下线,根据账号id 和 设备标识 + */ + @Override + public void replaced(Object loginId, String device) { + throw new ApiDisabledException(); + } + + /** + * 删除 Token-Id 映射 + */ + @Override + public void deleteTokenToIdMapping(String tokenValue) { + // not action + } + /** + * 更改 Token 指向的 账号Id 值 + */ + @Override + public void updateTokenToIdMapping(String tokenValue, Object loginId) { + // not action + } + /** + * 存储 Token-Id 映射 + */ + @Override + public void saveTokenToIdMapping(String tokenValue, Object loginId, long timeout) { + // not action + } + + // ------------------- 过期时间相关 ------------------- + + /** + * 获取当前登录者的 token 剩余有效时间 (单位: 秒) + */ + @Override + public long getTokenTimeout() { + return SaJwtUtil.getTimeout(getTokenValue(), jwtSecretKey()); + } + + + // ------------------- 会话管理 ------------------- + + /** + * 根据条件查询Token + */ + @Override + public List searchTokenValue(String keyword, int start, int size) { + throw new ApiDisabledException(); + } + + + // ------------------- Bean对象代理 ------------------- + + /** + * 返回全局配置对象的isShare属性 + * @return / + */ + @Override + public boolean getConfigOfIsShare() { + return false; + } + +} diff --git a/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForStateless.java b/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForStateless.java index 45be2c62..d6e667ea 100644 --- a/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForStateless.java +++ b/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForStateless.java @@ -3,6 +3,7 @@ package cn.dev33.satoken.jwt; import cn.dev33.satoken.SaManager; import cn.dev33.satoken.context.SaHolder; import cn.dev33.satoken.dao.SaTokenDao; +import cn.dev33.satoken.exception.ApiDisabledException; import cn.dev33.satoken.exception.NotLoginException; import cn.dev33.satoken.exception.SaTokenException; import cn.dev33.satoken.stp.SaLoginModel; @@ -18,12 +19,7 @@ import cn.dev33.satoken.stp.StpUtil; public class StpLogicJwtForStateless extends StpLogic { /** - * 异常描述 - */ - public static final String ERROR_MESSAGE = "This API is disabled"; - - /** - * 初始化StpLogic, 并指定账号类型 + * Sa-Token 整合 jwt -- stateless 无状态 * @param loginType 账号体系标识 */ public StpLogicJwtForStateless() { @@ -31,7 +27,7 @@ public class StpLogicJwtForStateless extends StpLogic { } /** - * 初始化StpLogic, 并指定账号类型 + * Sa-Token 整合 jwt -- stateless 无状态 * @param loginType 账号体系标识 */ public StpLogicJwtForStateless(String loginType) { @@ -56,8 +52,8 @@ public class StpLogicJwtForStateless extends StpLogic { * 创建一个TokenValue */ @Override - public String createTokenValue(Object loginId) { - return SaJwtUtil.createToken(loginId, jwtSecretKey()); + public String createTokenValue(Object loginId, String device, long timeout) { + return SaJwtUtil.createToken(loginType, loginId, device, timeout, jwtSecretKey()); } /** @@ -94,13 +90,7 @@ public class StpLogicJwtForStateless extends StpLogic { loginModel.build(getConfig()); // ------ 2、生成一个token - String tokenValue = SaJwtUtil.createToken( - loginType, - id, - loginModel.getDeviceOrDefault(), - loginModel.getTimeout(), - jwtSecretKey() - ); + String tokenValue = createTokenValue(id, loginModel.getDeviceOrDefault(), loginModel.getTimeout()); // 3、在当前会话写入tokenValue setTokenValue(tokenValue, loginModel.getCookieTimeout()); @@ -114,7 +104,7 @@ public class StpLogicJwtForStateless extends StpLogic { */ @Override public String getLoginIdNotHandle(String tokenValue) { - // 先验证 loginType,如果不符,相当于null + // 先验证 loginType,如果不符,则视为无效token,返回null String loginType = SaJwtUtil.getPayloadsNotCheck(tokenValue, jwtSecretKey()).getStr(SaJwtUtil.LOGIN_TYPE); if(getLoginType().equals(loginType) == false) { return null; @@ -181,11 +171,11 @@ public class StpLogicJwtForStateless extends StpLogic { // ------------------- Bean对象代理 ------------------- /** - * 返回持久化对象 + * [禁用] 返回持久化对象 */ @Override public SaTokenDao getSaTokenDao() { - throw new SaTokenException(ERROR_MESSAGE); + throw new ApiDisabledException(); } diff --git a/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForTokenStyle.java b/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForTokenStyle.java index a2a3e7b7..521e6273 100644 --- a/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForTokenStyle.java +++ b/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForTokenStyle.java @@ -4,15 +4,14 @@ import cn.dev33.satoken.stp.StpLogic; import cn.dev33.satoken.stp.StpUtil; /** - * Sa-Token 整合 jwt -- Token风格 + * Sa-Token 整合 jwt -- Token-Style * @author kong * */ public class StpLogicJwtForTokenStyle extends StpLogic { /** - * 初始化StpLogic, 并指定账号类型 - * @param loginType 账号体系标识 + * Sa-Token 整合 jwt -- Token-Style */ public StpLogicJwtForTokenStyle() { super(StpUtil.TYPE); @@ -42,7 +41,7 @@ public class StpLogicJwtForTokenStyle extends StpLogic { * @return 生成的tokenValue */ @Override - public String createTokenValue(Object loginId) { + public String createTokenValue(Object loginId, String device, long timeout) { return SaJwtUtil.createToken(loginId, jwtSecretKey()); } diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/test/java/com/pj/test/BasicsTest.java b/sa-token-starter/sa-token-spring-boot-starter/src/test/java/com/pj/test/BasicsTest.java index ba9679ce..c93b7bdc 100644 --- a/sa-token-starter/sa-token-spring-boot-starter/src/test/java/com/pj/test/BasicsTest.java +++ b/sa-token-starter/sa-token-spring-boot-starter/src/test/java/com/pj/test/BasicsTest.java @@ -7,6 +7,7 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @@ -32,13 +33,13 @@ import cn.dev33.satoken.util.SaTokenConsts; public class BasicsTest { // 持久化Bean - static SaTokenDao dao; + @Autowired(required = false) + SaTokenDao dao = SaManager.getSaTokenDao(); // 开始 @BeforeClass public static void beforeClass() { System.out.println("\n\n------------------------ 基础测试 star ..."); - dao = SaManager.getSaTokenDao(); } // 结束 diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/test/java/com/pj/test/ManyLoginTest.java b/sa-token-starter/sa-token-spring-boot-starter/src/test/java/com/pj/test/ManyLoginTest.java index 83813ae3..141f4538 100644 --- a/sa-token-starter/sa-token-spring-boot-starter/src/test/java/com/pj/test/ManyLoginTest.java +++ b/sa-token-starter/sa-token-spring-boot-starter/src/test/java/com/pj/test/ManyLoginTest.java @@ -7,6 +7,7 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @@ -28,13 +29,13 @@ import cn.dev33.satoken.stp.StpUtil; public class ManyLoginTest { // 持久化Bean - static SaTokenDao dao; + @Autowired(required = false) + SaTokenDao dao = SaManager.getSaTokenDao(); // 开始 @BeforeClass public static void beforeClass() { System.out.println("\n------------ 多端登录测试 star ..."); - dao = SaManager.getSaTokenDao(); } // 结束 @AfterClass