getPermissionList(Object loginId) {
+ return stpLogic.getPermissionList(loginId);
+ }
+
+ /**
+ * 判断:当前账号是否含有指定权限, 返回true或false
+ * @param permission 权限码
+ * @return 是否含有指定权限
+ */
+ public static boolean hasPermission(String permission) {
+ return stpLogic.hasPermission(permission);
+ }
+
+ /**
+ * 判断:指定账号id是否含有指定权限, 返回true或false
+ * @param loginId 账号id
+ * @param permission 权限码
+ * @return 是否含有指定权限
+ */
+ public static boolean hasPermission(Object loginId, String permission) {
+ return stpLogic.hasPermission(loginId, permission);
+ }
+
+ /**
+ * 判断:当前账号是否含有指定权限, [指定多个,必须全部具有]
+ * @param permissionArray 权限码数组
+ * @return true 或 false
+ */
+ public static boolean hasPermissionAnd(String... permissionArray){
+ return stpLogic.hasPermissionAnd(permissionArray);
+ }
+
+ /**
+ * 判断:当前账号是否含有指定权限 [指定多个,只要其一验证通过即可]
+ * @param permissionArray 权限码数组
+ * @return true 或 false
+ */
+ public static boolean hasPermissionOr(String... permissionArray){
+ return stpLogic.hasPermissionOr(permissionArray);
+ }
+
+ /**
+ * 校验:当前账号是否含有指定权限, 如果验证未通过,则抛出异常: NotPermissionException
+ * @param permission 权限码
+ */
+ public static void checkPermission(String permission) {
+ stpLogic.checkPermission(permission);
+ }
+
+ /**
+ * 校验:当前账号是否含有指定权限 [指定多个,必须全部验证通过]
+ * @param permissionArray 权限码数组
+ */
+ public static void checkPermissionAnd(String... permissionArray) {
+ stpLogic.checkPermissionAnd(permissionArray);
+ }
+
+ /**
+ * 校验:当前账号是否含有指定权限 [指定多个,只要其一验证通过即可]
+ * @param permissionArray 权限码数组
+ */
+ public static void checkPermissionOr(String... permissionArray) {
+ stpLogic.checkPermissionOr(permissionArray);
+ }
+
+
+ // =================== id 反查token 相关操作 ===================
+
+ /**
+ * 获取指定账号id的tokenValue
+ * 在配置为允许并发登录时,此方法只会返回队列的最后一个token,
+ * 如果你需要返回此账号id的所有token,请调用 getTokenValueListByLoginId
+ * @param loginId 账号id
+ * @return token值
+ */
+ public static String getTokenValueByLoginId(Object loginId) {
+ return stpLogic.getTokenValueByLoginId(loginId);
+ }
+
+ /**
+ * 获取指定账号id指定设备类型端的tokenValue
+ *
在配置为允许并发登录时,此方法只会返回队列的最后一个token,
+ * 如果你需要返回此账号id的所有token,请调用 getTokenValueListByLoginId
+ * @param loginId 账号id
+ * @param device 设备类型
+ * @return token值
+ */
+ public static String getTokenValueByLoginId(Object loginId, String device) {
+ return stpLogic.getTokenValueByLoginId(loginId, device);
+ }
+
+ /**
+ * 获取指定账号id的tokenValue集合
+ * @param loginId 账号id
+ * @return 此loginId的所有相关token
+ */
+ public static List getTokenValueListByLoginId(Object loginId) {
+ return stpLogic.getTokenValueListByLoginId(loginId);
+ }
+
+ /**
+ * 获取指定账号id指定设备类型端的tokenValue 集合
+ * @param loginId 账号id
+ * @param device 设备类型
+ * @return 此loginId的所有相关token
+ */
+ public static List getTokenValueListByLoginId(Object loginId, String device) {
+ return stpLogic.getTokenValueListByLoginId(loginId, device);
+ }
+
+ /**
+ * 返回当前会话的登录设备类型
+ * @return 当前令牌的登录设备类型
+ */
+ public static String getLoginDevice() {
+ return stpLogic.getLoginDevice();
+ }
+
+
+ // =================== 会话管理 ===================
+
+ /**
+ * 根据条件查询Token
+ * @param keyword 关键字
+ * @param start 开始处索引 (-1代表查询所有)
+ * @param size 获取数量
+ * @return token集合
+ */
+ public static List searchTokenValue(String keyword, int start, int size) {
+ return stpLogic.searchTokenValue(keyword, start, size);
+ }
+
+ /**
+ * 根据条件查询SessionId
+ * @param keyword 关键字
+ * @param start 开始处索引 (-1代表查询所有)
+ * @param size 获取数量
+ * @return sessionId集合
+ */
+ public static List searchSessionId(String keyword, int start, int size) {
+ return stpLogic.searchSessionId(keyword, start, size);
+ }
+
+ /**
+ * 根据条件查询Token专属Session的Id
+ * @param keyword 关键字
+ * @param start 开始处索引 (-1代表查询所有)
+ * @param size 获取数量
+ * @return sessionId集合
+ */
+ public static List searchTokenSessionId(String keyword, int start, int size) {
+ return stpLogic.searchTokenSessionId(keyword, start, size);
+ }
+
+
+ // ------------------- 账号封禁 -------------------
+
+ /**
+ * 封禁指定账号
+ * 此方法不会直接将此账号id踢下线,而是在对方再次登录时抛出`DisableLoginException`异常
+ * @param loginId 指定账号id
+ * @param disableTime 封禁时间, 单位: 秒 (-1=永久封禁)
+ */
+ public static void disable(Object loginId, long disableTime) {
+ stpLogic.disable(loginId, disableTime);
+ }
+
+ /**
+ * 指定账号是否已被封禁 (true=已被封禁, false=未被封禁)
+ * @param loginId 账号id
+ * @return see note
+ */
+ public static boolean isDisable(Object loginId) {
+ return stpLogic.isDisable(loginId);
+ }
+
+ /**
+ * 获取指定账号剩余封禁时间,单位:秒(-1=永久封禁,-2=未被封禁)
+ * @param loginId 账号id
+ * @return see note
+ */
+ public static long getDisableTime(Object loginId) {
+ return stpLogic.getDisableTime(loginId);
+ }
+
+ /**
+ * 解封指定账号
+ * @param loginId 账号id
+ */
+ public static void untieDisable(Object loginId) {
+ stpLogic.untieDisable(loginId);
+ }
+
+
+ // =================== 身份切换 ===================
+
+ /**
+ * 临时切换身份为指定账号id
+ * @param loginId 指定loginId
+ */
+ public static void switchTo(Object loginId) {
+ stpLogic.switchTo(loginId);
+ }
+
+ /**
+ * 结束临时切换身份
+ */
+ public static void endSwitch() {
+ stpLogic.endSwitch();
+ }
+
+ /**
+ * 当前是否正处于[身份临时切换]中
+ * @return 是否正处于[身份临时切换]中
+ */
+ public static boolean isSwitch() {
+ return stpLogic.isSwitch();
+ }
+
+ /**
+ * 在一个代码段里方法内,临时切换身份为指定账号id
+ * @param loginId 指定账号id
+ * @param function 要执行的方法
+ */
+ public static void switchTo(Object loginId, SaFunction function) {
+ stpLogic.switchTo(loginId, function);
+ }
+
+
+ // ------------------- 二级认证 -------------------
+
+ /**
+ * 在当前会话 开启二级认证
+ * @param safeTime 维持时间 (单位: 秒)
+ */
+ public static void openSafe(long safeTime) {
+ stpLogic.openSafe(safeTime);
+ }
+
+ /**
+ * 当前会话 是否处于二级认证时间内
+ * @return true=二级认证已通过, false=尚未进行二级认证或认证已超时
+ */
+ public static boolean isSafe() {
+ return stpLogic.isSafe();
+ }
+
+ /**
+ * 检查当前会话是否已通过二级认证,如未通过则抛出异常
+ */
+ public static void checkSafe() {
+ stpLogic.checkSafe();
+ }
+
+ /**
+ * 获取当前会话的二级认证剩余有效时间 (单位: 秒, 返回-2代表尚未通过二级认证)
+ * @return 剩余有效时间
+ */
+ public static long getSafeTime() {
+ return stpLogic.getSafeTime();
+ }
+
+ /**
+ * 在当前会话 结束二级认证
+ */
+ public static void closeSafe() {
+ stpLogic.closeSafe();
+ }
+
+
+ // =================== 历史API,兼容旧版本 ===================
+
+ /**
+ *
本函数设计已过时,未来版本可能移除此函数,请及时更换为 StpUtil.getLoginType() ,使用方式保持不变
+ *
+ * 获取当前StpLogin的loginKey
+ * @return 当前StpLogin的loginKey
+ */
+ @Deprecated
+ public static String getLoginKey(){
+ return stpLogic.getLoginType();
+ }
+
+ /**
+ * 本函数设计已过时,未来版本可能移除此函数,请及时更换为 StpUtil.login() ,使用方式保持不变
+ *
+ * 在当前会话上登录id
+ * @param loginId 登录id,建议的类型:(long | int | String)
+ */
+ @Deprecated
+ public static void setLoginId(Object loginId) {
+ stpLogic.login(loginId);
+ }
+
+ /**
+ * 本函数设计已过时,未来版本可能移除此函数,请及时更换为 StpUtil.login() ,使用方式保持不变
+ *
+ * 在当前会话上登录id, 并指定登录设备类型
+ * @param loginId 登录id,建议的类型:(long | int | String)
+ * @param device 设备类型
+ */
+ @Deprecated
+ public static void setLoginId(Object loginId, String device) {
+ stpLogic.login(loginId, device);
+ }
+
+ /**
+ * 本函数设计已过时,未来版本可能移除此函数,请及时更换为 StpUtil.login() ,使用方式保持不变
+ *
+ * 在当前会话上登录id, 并指定登录设备类型
+ * @param loginId 登录id,建议的类型:(long | int | String)
+ * @param isLastingCookie 是否为持久Cookie
+ */
+ @Deprecated
+ public static void setLoginId(Object loginId, boolean isLastingCookie) {
+ stpLogic.login(loginId, isLastingCookie);
+ }
+
+ /**
+ * 本函数设计已过时,未来版本可能移除此函数,请及时更换为 StpUtil.login() ,使用方式保持不变
+ *
+ * 在当前会话上登录id, 并指定所有登录参数Model
+ * @param loginId 登录id,建议的类型:(long | int | String)
+ * @param loginModel 此次登录的参数Model
+ */
+ @Deprecated
+ public static void setLoginId(Object loginId, SaLoginModel loginModel) {
+ stpLogic.login(loginId, loginModel);
+ }
+
+ /**
+ * 本函数设计已过时,未来版本可能移除此函数,请及时更换为 StpUtil.kickout() ,使用方式保持不变
+ *
+ * 会话注销,根据账号id (踢人下线)
+ * 当对方再次访问系统时,会抛出NotLoginException异常,场景值=-2
+ * @param loginId 账号id
+ */
+ @Deprecated
+ public static void logoutByLoginId(Object loginId) {
+ stpLogic.kickout(loginId);
+ }
+
+ /**
+ *
本函数设计已过时,未来版本可能移除此函数,请及时更换为 StpUtil.kickout() ,使用方式保持不变
+ *
+ * 会话注销,根据账号id and 设备类型 (踢人下线)
+ * 当对方再次访问系统时,会抛出NotLoginException异常,场景值=-2
+ * @param loginId 账号id
+ * @param device 设备类型 (填null代表注销所有设备类型)
+ */
+ @Deprecated
+ public static void logoutByLoginId(Object loginId, String device) {
+ stpLogic.kickout(loginId, device);
+ }
+
+}
diff --git a/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/test/AtController.java b/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/test/AtController.java
new file mode 100644
index 00000000..dc7c6f95
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/test/AtController.java
@@ -0,0 +1,80 @@
+package com.pj.test;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import cn.dev33.satoken.annotation.SaCheckBasic;
+import cn.dev33.satoken.annotation.SaCheckLogin;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.dev33.satoken.annotation.SaCheckRole;
+import cn.dev33.satoken.annotation.SaCheckSafe;
+import cn.dev33.satoken.annotation.SaMode;
+import cn.dev33.satoken.stp.StpUtil;
+import cn.dev33.satoken.util.SaResult;
+
+/**
+ * 注解鉴权测试
+ * @author kong
+ *
+ */
+@RestController
+@RequestMapping("/at/")
+public class AtController {
+
+ // 登录认证,登录之后才可以进入方法 ---- http://localhost:8081/at/checkLogin
+ @SaCheckLogin
+ @RequestMapping("checkLogin")
+ public SaResult checkLogin() {
+ return SaResult.ok();
+ }
+
+ // 权限认证,具备user-add权限才可以进入方法 ---- http://localhost:8081/at/checkPermission
+ @SaCheckPermission("user-add")
+ @RequestMapping("checkPermission")
+ public SaResult checkPermission() {
+ return SaResult.ok();
+ }
+
+ // 权限认证,同时具备所有权限才可以进入 ---- http://localhost:8081/at/checkPermissionAnd
+ @SaCheckPermission({"user-add", "user-delete", "user-update"})
+ @RequestMapping("checkPermissionAnd")
+ public SaResult checkPermissionAnd() {
+ return SaResult.ok();
+ }
+
+ // 权限认证,只要具备其中一个就可以进入 ---- http://localhost:8081/at/checkPermissionOr
+ @SaCheckPermission(value = {"user-add", "user-delete", "user-update"}, mode = SaMode.OR)
+ @RequestMapping("checkPermissionOr")
+ public SaResult checkPermissionOr() {
+ return SaResult.ok();
+ }
+
+ // 角色认证,只有具备admin角色才可以进入 ---- http://localhost:8081/at/checkRole
+ @SaCheckRole("admin")
+ @RequestMapping("checkRole")
+ public SaResult checkRole() {
+ return SaResult.ok();
+ }
+
+ // 完成二级认证 ---- http://localhost:8081/at/openSafe
+ @RequestMapping("openSafe")
+ public SaResult openSafe() {
+ StpUtil.openSafe(200); // 打开二级认证,有效期为200秒
+ return SaResult.ok();
+ }
+
+ // 通过二级认证后才可以进入 ---- http://localhost:8081/at/checkSafe
+ @SaCheckSafe
+ @RequestMapping("checkSafe")
+ public SaResult checkSafe() {
+ return SaResult.ok();
+ }
+
+ // 通过Basic认证后才可以进入 ---- http://localhost:8081/at/checkBasic
+ @SaCheckBasic(account = "sa:123456")
+ @RequestMapping("checkBasic")
+ public SaResult checkBasic() {
+ return SaResult.ok();
+ }
+
+}
diff --git a/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/test/LoginController.java b/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/test/LoginController.java
new file mode 100644
index 00000000..ea94cfa7
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/test/LoginController.java
@@ -0,0 +1,48 @@
+package com.pj.test;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import cn.dev33.satoken.stp.StpUtil;
+import cn.dev33.satoken.util.SaResult;
+
+/**
+ * 登录测试
+ * @author kong
+ *
+ */
+@RestController
+@RequestMapping("/acc/")
+public class LoginController {
+
+ // 测试登录 ---- http://localhost:8081/acc/doLogin?name=zhang&pwd=123456
+ @RequestMapping("doLogin")
+ public SaResult doLogin(String name, String pwd) {
+ // 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对
+ if("zhang".equals(name) && "123456".equals(pwd)) {
+ StpUtil.login(10001);
+ return SaResult.ok("登录成功");
+ }
+ return SaResult.error("登录失败");
+ }
+
+ // 查询登录状态 ---- http://localhost:8081/acc/isLogin
+ @RequestMapping("isLogin")
+ public SaResult isLogin() {
+ return SaResult.ok("是否登录:" + StpUtil.isLogin());
+ }
+
+ // 查询 Token 信息 ---- http://localhost:8081/acc/tokenInfo
+ @RequestMapping("tokenInfo")
+ public SaResult tokenInfo() {
+ return SaResult.data(StpUtil.getTokenInfo());
+ }
+
+ // 测试注销 ---- http://localhost:8081/acc/logout
+ @RequestMapping("logout")
+ public SaResult logout() {
+ StpUtil.logout();
+ return SaResult.ok();
+ }
+
+}
diff --git a/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/test/StressTestController.java b/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/test/StressTestController.java
new file mode 100644
index 00000000..5c0b3ce1
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/test/StressTestController.java
@@ -0,0 +1,61 @@
+package com.pj.test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.pj.util.AjaxJson;
+import com.pj.util.Ttime;
+
+import cn.dev33.satoken.stp.StpUtil;
+
+/**
+ * 压力测试
+ * @author kong
+ *
+ */
+@RestController
+@RequestMapping("/s-test/")
+public class StressTestController {
+
+ // 测试 浏览器访问: http://localhost:8081/s-test/login
+ // 测试前,请先将 is-read-cookie 配置为 false
+ @RequestMapping("login")
+ public AjaxJson login() {
+// StpUtil.getTokenSession().logout();
+// StpUtil.logoutByLoginId(10001);
+
+ int count = 10; // 循环多少轮
+ int loginCount = 10000; // 每轮循环多少次
+
+ // 循环10次 取平均时间
+ List list = new ArrayList<>();
+ for (int i = 1; i <= count; i++) {
+ System.out.println("\n---------------------第" + i + "轮---------------------");
+ Ttime t = new Ttime().start();
+ // 每次登录的次数
+ for (int j = 1; j <= loginCount; j++) {
+ StpUtil.login("1000" + j, "PC-" + j);
+ if(j % 1000 == 0) {
+ System.out.println("已登录:" + j);
+ }
+ }
+ t.end();
+ list.add((t.returnMs() + 0.0) / 1000);
+ System.out.println("第" + i + "轮" + "用时:" + t.toString());
+ }
+// System.out.println(((SaTokenDaoDefaultImpl)SaTokenManager.getSaTokenDao()).dataMap.size());
+
+ System.out.println("\n---------------------测试结果---------------------");
+ System.out.println(list.size() + "次测试: " + list);
+ double ss = 0;
+ for (int i = 0; i < list.size(); i++) {
+ ss += list.get(i);
+ }
+ System.out.println("平均用时: " + ss / list.size());
+ return AjaxJson.getSuccess();
+ }
+
+}
diff --git a/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/test/TestController.java b/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/test/TestController.java
new file mode 100644
index 00000000..0712eb2d
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/test/TestController.java
@@ -0,0 +1,251 @@
+package com.pj.test;
+
+import java.util.Date;
+import java.util.List;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.pj.util.AjaxJson;
+import com.pj.util.Ttime;
+
+import cn.dev33.satoken.annotation.SaCheckLogin;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.dev33.satoken.annotation.SaCheckRole;
+import cn.dev33.satoken.annotation.SaMode;
+import cn.dev33.satoken.session.SaSessionCustomUtil;
+import cn.dev33.satoken.stp.SaTokenInfo;
+import cn.dev33.satoken.stp.StpUtil;
+
+/**
+ * 测试专用Controller
+ * @author kong
+ *
+ */
+@RestController
+@RequestMapping("/test/")
+public class TestController {
+
+ // 测试登录接口, 浏览器访问: http://localhost:8081/test/login
+ @RequestMapping("login")
+ public AjaxJson login(@RequestParam(defaultValue="10001") String id) {
+ System.out.println("======================= 进入方法,测试登录接口 ========================= ");
+ System.out.println("当前会话的token:" + StpUtil.getTokenValue());
+ System.out.println("当前是否登录:" + StpUtil.isLogin());
+ System.out.println("当前登录账号:" + StpUtil.getLoginIdDefaultNull());
+
+ StpUtil.login(id); // 在当前会话登录此账号
+ System.out.println("登录成功");
+ System.out.println("当前是否登录:" + StpUtil.isLogin());
+ System.out.println("当前登录账号:" + StpUtil.getLoginId());
+// System.out.println("当前登录账号并转为int:" + StpUtil.getLoginIdAsInt());
+ System.out.println("当前登录设备:" + StpUtil.getLoginDevice());
+// System.out.println("当前token信息:" + StpUtil.getTokenInfo());
+
+ return AjaxJson.getSuccess();
+ }
+
+ // 测试退出登录 , 浏览器访问: http://localhost:8081/test/logout
+ @RequestMapping("logout")
+ public AjaxJson logout() {
+ StpUtil.logout();
+// StpUtil.logoutByLoginId(10001);
+ return AjaxJson.getSuccess();
+ }
+
+ // 测试角色接口, 浏览器访问: http://localhost:8081/test/testRole
+ @RequestMapping("testRole")
+ public AjaxJson testRole() {
+ System.out.println("======================= 进入方法,测试角色接口 ========================= ");
+
+ System.out.println("是否具有角色标识 user " + StpUtil.hasRole("user"));
+ System.out.println("是否具有角色标识 admin " + StpUtil.hasRole("admin"));
+
+ System.out.println("没有admin权限就抛出异常");
+ StpUtil.checkRole("admin");
+
+ System.out.println("在【admin、user】中只要拥有一个就不会抛出异常");
+ StpUtil.checkRoleOr("admin", "user");
+
+ System.out.println("在【admin、user】中必须全部拥有才不会抛出异常");
+ StpUtil.checkRoleAnd("admin", "user");
+
+ System.out.println("角色测试通过");
+
+ return AjaxJson.getSuccess();
+ }
+
+ // 测试权限接口, 浏览器访问: http://localhost:8081/test/testJur
+ @RequestMapping("testJur")
+ public AjaxJson testJur() {
+ System.out.println("======================= 进入方法,测试权限接口 ========================= ");
+
+ System.out.println("是否具有权限101" + StpUtil.hasPermission("101"));
+ System.out.println("是否具有权限user-add" + StpUtil.hasPermission("user-add"));
+ System.out.println("是否具有权限article-get" + StpUtil.hasPermission("article-get"));
+
+ System.out.println("没有user-add权限就抛出异常");
+ StpUtil.checkPermission("user-add");
+
+ System.out.println("在【101、102】中只要拥有一个就不会抛出异常");
+ StpUtil.checkPermissionOr("101", "102");
+
+ System.out.println("在【101、102】中必须全部拥有才不会抛出异常");
+ StpUtil.checkPermissionAnd("101", "102");
+
+ System.out.println("权限测试通过");
+
+ return AjaxJson.getSuccess();
+ }
+
+ // 测试会话session接口, 浏览器访问: http://localhost:8081/test/session
+ @RequestMapping("session")
+ public AjaxJson session() throws JsonProcessingException {
+ System.out.println("======================= 进入方法,测试会话session接口 ========================= ");
+ System.out.println("当前是否登录:" + StpUtil.isLogin());
+ System.out.println("当前登录账号session的id" + StpUtil.getSession().getId());
+ System.out.println("当前登录账号session的id" + StpUtil.getSession().getId());
+ System.out.println("测试取值name:" + StpUtil.getSession().get("name"));
+ StpUtil.getSession().set("name", new Date()); // 写入一个值
+ System.out.println("测试取值name:" + StpUtil.getSession().get("name"));
+ System.out.println( new ObjectMapper().writeValueAsString(StpUtil.getSession()));
+ return AjaxJson.getSuccess();
+ }
+
+ // 测试自定义session接口, 浏览器访问: http://localhost:8081/test/session2
+ @RequestMapping("session2")
+ public AjaxJson session2() {
+ System.out.println("======================= 进入方法,测试自定义session接口 ========================= ");
+ // 自定义session就是无需登录也可以使用 的session :比如拿用户的手机号当做 key, 来获取 session
+ System.out.println("自定义 session的id为:" + SaSessionCustomUtil.getSessionById("1895544896").getId());
+ System.out.println("测试取值name:" + SaSessionCustomUtil.getSessionById("1895544896").get("name"));
+ SaSessionCustomUtil.getSessionById("1895544896").set("name", "张三"); // 写入值
+ System.out.println("测试取值name:" + SaSessionCustomUtil.getSessionById("1895544896").get("name"));
+ System.out.println("测试取值name:" + SaSessionCustomUtil.getSessionById("1895544896").get("name"));
+ return AjaxJson.getSuccess();
+ }
+
+ // ----------
+ // 测试token专属session, 浏览器访问: http://localhost:8081/test/getTokenSession
+ @RequestMapping("getTokenSession")
+ public AjaxJson getTokenSession() {
+ System.out.println("======================= 进入方法,测试会话session接口 ========================= ");
+ System.out.println("当前是否登录:" + StpUtil.isLogin());
+ System.out.println("当前token专属session: " + StpUtil.getTokenSession().getId());
+
+ System.out.println("测试取值name:" + StpUtil.getTokenSession().get("name"));
+ StpUtil.getTokenSession().set("name", "张三"); // 写入一个值
+ System.out.println("测试取值name:" + StpUtil.getTokenSession().get("name"));
+
+ return AjaxJson.getSuccess();
+ }
+
+ // 打印当前token信息, 浏览器访问: http://localhost:8081/test/tokenInfo
+ @RequestMapping("tokenInfo")
+ public AjaxJson tokenInfo() {
+ System.out.println("======================= 进入方法,打印当前token信息 ========================= ");
+ SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
+ System.out.println(tokenInfo);
+ return AjaxJson.getSuccessData(tokenInfo);
+ }
+
+ // 测试注解式鉴权, 浏览器访问: http://localhost:8081/test/atCheck
+ @SaCheckLogin // 注解式鉴权:当前会话必须登录才能通过
+ @SaCheckRole("super-admin") // 注解式鉴权:当前会话必须具有指定角色标识才能通过
+ @SaCheckPermission("user-add") // 注解式鉴权:当前会话必须具有指定权限才能通过
+ @RequestMapping("atCheck")
+ public AjaxJson atCheck() {
+ System.out.println("======================= 进入方法,测试注解鉴权接口 ========================= ");
+ System.out.println("只有通过注解鉴权,才能进入此方法");
+// StpUtil.checkActivityTimeout();
+// StpUtil.updateLastActivityToNow();
+ return AjaxJson.getSuccess();
+ }
+
+ // 测试注解式鉴权, 浏览器访问: http://localhost:8081/test/atJurOr
+ @RequestMapping("atJurOr")
+ @SaCheckPermission(value = {"user-add", "user-all", "user-delete"}, mode = SaMode.OR) // 注解式鉴权:只要具有其中一个权限即可通过校验
+ public AjaxJson atJurOr() {
+ return AjaxJson.getSuccessData("用户信息");
+ }
+
+ // [活动时间] 续签: http://localhost:8081/test/rene
+ @RequestMapping("rene")
+ public AjaxJson rene() {
+ StpUtil.checkActivityTimeout();
+ StpUtil.updateLastActivityToNow();
+ return AjaxJson.getSuccess("续签成功");
+ }
+
+ // 测试踢人下线 浏览器访问: http://localhost:8081/test/kickOut
+ @RequestMapping("kickOut")
+ public AjaxJson kickOut() {
+ // 先登录上
+ StpUtil.login(10001);
+ // 踢下线
+ StpUtil.kickout(10001);
+ // 再尝试获取
+ StpUtil.getLoginId();
+ // 返回
+ return AjaxJson.getSuccess();
+ }
+
+ // 测试登录接口, 按照设备登录, 浏览器访问: http://localhost:8081/test/login2
+ @RequestMapping("login2")
+ public AjaxJson login2(@RequestParam(defaultValue="10001") String id, @RequestParam(defaultValue="PC") String device) {
+ StpUtil.login(id, device);
+ return AjaxJson.getSuccess();
+ }
+
+ // 测试身份临时切换: http://localhost:8081/test/switchTo
+ @RequestMapping("switchTo")
+ public AjaxJson switchTo() {
+ System.out.println("当前会话身份:" + StpUtil.getLoginIdDefaultNull());
+ System.out.println("是否正在身份临时切换中: " + StpUtil.isSwitch());
+ StpUtil.switchTo(10044, () -> {
+ System.out.println("是否正在身份临时切换中: " + StpUtil.isSwitch());
+ System.out.println("当前会话身份已被切换为:" + StpUtil.getLoginId());
+ });
+ System.out.println("是否正在身份临时切换中: " + StpUtil.isSwitch());
+ return AjaxJson.getSuccess();
+ }
+
+ // 测试会话治理 浏览器访问: http://localhost:8081/test/search
+ @RequestMapping("search")
+ public AjaxJson search() {
+ System.out.println("--------------");
+ Ttime t = new Ttime().start();
+ List tokenValue = StpUtil.searchTokenValue("8feb8265f773", 0, 10);
+ for (String v : tokenValue) {
+// SaSession session = StpUtil.getSessionBySessionId(sid);
+ System.out.println(v);
+ }
+ System.out.println("用时:" + t.end().toString());
+ return AjaxJson.getSuccess();
+ }
+
+ // 测试指定设备登录 浏览器访问: http://localhost:8081/test/loginByDevice
+ @RequestMapping("loginByDevice")
+ public AjaxJson loginByDevice() {
+ System.out.println("--------------");
+ StpUtil.login(10001, "PC");
+ return AjaxJson.getSuccessData("登录成功");
+ }
+
+ // 测试 浏览器访问: http://localhost:8081/test/test
+ @RequestMapping("test")
+ public AjaxJson test() {
+ System.out.println("------------进来了");
+ return AjaxJson.getSuccess();
+ }
+
+ // 测试 浏览器访问: http://localhost:8081/test/test2
+ @RequestMapping("test2")
+ public AjaxJson test2() {
+ return AjaxJson.getSuccess();
+ }
+
+}
diff --git a/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/util/AjaxJson.java b/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/util/AjaxJson.java
new file mode 100644
index 00000000..768d0578
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/util/AjaxJson.java
@@ -0,0 +1,162 @@
+package com.pj.util;
+
+import java.io.Serializable;
+import java.util.List;
+
+
+/**
+ * ajax请求返回Json格式数据的封装
+ */
+public class AjaxJson implements Serializable{
+
+ private static final long serialVersionUID = 1L; // 序列化版本号
+
+ public static final int CODE_SUCCESS = 200; // 成功状态码
+ public static final int CODE_ERROR = 500; // 错误状态码
+ public static final int CODE_WARNING = 501; // 警告状态码
+ public static final int CODE_NOT_JUR = 403; // 无权限状态码
+ public static final int CODE_NOT_LOGIN = 401; // 未登录状态码
+ public static final int CODE_INVALID_REQUEST = 400; // 无效请求状态码
+
+ public int code; // 状态码
+ public String msg; // 描述信息
+ public Object data; // 携带对象
+ public Long dataCount; // 数据总数,用于分页
+
+ /**
+ * 返回code
+ * @return
+ */
+ public int getCode() {
+ return this.code;
+ }
+
+ /**
+ * 给msg赋值,连缀风格
+ */
+ public AjaxJson setMsg(String msg) {
+ this.msg = msg;
+ return this;
+ }
+ public String getMsg() {
+ return this.msg;
+ }
+
+ /**
+ * 给data赋值,连缀风格
+ */
+ public AjaxJson setData(Object data) {
+ this.data = data;
+ return this;
+ }
+
+ /**
+ * 将data还原为指定类型并返回
+ */
+ @SuppressWarnings("unchecked")
+ public T getData(Class cs) {
+ return (T) data;
+ }
+
+ // ============================ 构建 ==================================
+
+ public AjaxJson(int code, String msg, Object data, Long dataCount) {
+ this.code = code;
+ this.msg = msg;
+ this.data = data;
+ this.dataCount = dataCount;
+ }
+
+ // 返回成功
+ public static AjaxJson getSuccess() {
+ return new AjaxJson(CODE_SUCCESS, "ok", null, null);
+ }
+ public static AjaxJson getSuccess(String msg) {
+ return new AjaxJson(CODE_SUCCESS, msg, null, null);
+ }
+ public static AjaxJson getSuccess(String msg, Object data) {
+ return new AjaxJson(CODE_SUCCESS, msg, data, null);
+ }
+ public static AjaxJson getSuccessData(Object data) {
+ return new AjaxJson(CODE_SUCCESS, "ok", data, null);
+ }
+ public static AjaxJson getSuccessArray(Object... data) {
+ return new AjaxJson(CODE_SUCCESS, "ok", data, null);
+ }
+
+ // 返回失败
+ public static AjaxJson getError() {
+ return new AjaxJson(CODE_ERROR, "error", null, null);
+ }
+ public static AjaxJson getError(String msg) {
+ return new AjaxJson(CODE_ERROR, msg, null, null);
+ }
+
+ // 返回警告
+ public static AjaxJson getWarning() {
+ return new AjaxJson(CODE_ERROR, "warning", null, null);
+ }
+ public static AjaxJson getWarning(String msg) {
+ return new AjaxJson(CODE_WARNING, msg, null, null);
+ }
+
+ // 返回未登录
+ public static AjaxJson getNotLogin() {
+ return new AjaxJson(CODE_NOT_LOGIN, "未登录,请登录后再次访问", null, null);
+ }
+
+ // 返回没有权限的
+ public static AjaxJson getNotJur(String msg) {
+ return new AjaxJson(CODE_NOT_JUR, msg, null, null);
+ }
+
+ // 返回一个自定义状态码的
+ public static AjaxJson get(int code, String msg){
+ return new AjaxJson(code, msg, null, null);
+ }
+
+ // 返回分页和数据的
+ public static AjaxJson getPageData(Long dataCount, Object data){
+ return new AjaxJson(CODE_SUCCESS, "ok", data, dataCount);
+ }
+
+ // 返回,根据受影响行数的(大于0=ok,小于0=error)
+ public static AjaxJson getByLine(int line){
+ if(line > 0){
+ return getSuccess("ok", line);
+ }
+ return getError("error").setData(line);
+ }
+
+ // 返回,根据布尔值来确定最终结果的 (true=ok,false=error)
+ public static AjaxJson getByBoolean(boolean b){
+ return b ? getSuccess("ok") : getError("error");
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @SuppressWarnings("rawtypes")
+ @Override
+ public String toString() {
+ String data_string = null;
+ if(data == null){
+
+ } else if(data instanceof List){
+ data_string = "List(length=" + ((List)data).size() + ")";
+ } else {
+ data_string = data.toString();
+ }
+ return "{"
+ + "\"code\": " + this.getCode()
+ + ", \"msg\": \"" + this.getMsg() + "\""
+ + ", \"data\": " + data_string
+ + ", \"dataCount\": " + dataCount
+ + "}";
+ }
+
+
+
+
+
+}
diff --git a/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/util/Ttime.java b/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/util/Ttime.java
new file mode 100644
index 00000000..cb17dcaa
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/util/Ttime.java
@@ -0,0 +1,63 @@
+package com.pj.util;
+
+
+/**
+ * 用于测试用时
+ * @author kong
+ *
+ */
+public class Ttime {
+
+ private long start=0; //开始时间
+ private long end=0; //结束时间
+
+ public static Ttime t = new Ttime(); //static快捷使用
+
+ /**
+ * 开始计时
+ * @return
+ */
+ public Ttime start() {
+ start=System.currentTimeMillis();
+ return this;
+ }
+
+
+ /**
+ * 结束计时
+ */
+ public Ttime end() {
+ end=System.currentTimeMillis();
+ return this;
+ }
+
+
+ /**
+ * 返回所用毫秒数
+ */
+ public long returnMs() {
+ return end-start;
+ }
+
+ /**
+ * 格式化输出结果
+ */
+ public void outTime() {
+ System.out.println(this.toString());
+ }
+
+ /**
+ * 结束并格式化输出结果
+ */
+ public void endOutTime() {
+ this.end().outTime();
+ }
+
+ @Override
+ public String toString() {
+ return (returnMs() + 0.0) / 1000 + "s"; // 格式化为:0.01s
+ }
+
+
+
+}
diff --git a/sa-token-demo/sa-token-demo-springboot-redis/src/main/resources/application.yml b/sa-token-demo/sa-token-demo-springboot-redis/src/main/resources/application.yml
new file mode 100644
index 00000000..cb63067a
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-springboot-redis/src/main/resources/application.yml
@@ -0,0 +1,49 @@
+# 端口
+server:
+ port: 8081
+
+# sa-token配置
+sa-token:
+ # token名称 (同时也是cookie名称)
+ token-name: satoken
+ # token有效期,单位s 默认30天, -1代表永不过期
+ timeout: 2592000
+ # token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
+ activity-timeout: -1
+ # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
+ is-concurrent: true
+ # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
+ is-share: true
+ # token风格
+ token-style: uuid
+ # 是否输出操作日志
+ is-log: false
+
+spring:
+ # redis配置
+ redis:
+ # Redis数据库索引(默认为0)
+ database: 0
+ # Redis服务器地址
+ host: 127.0.0.1
+ # Redis服务器连接端口
+ port: 6379
+ # Redis服务器连接密码(默认为空)
+ password:
+ # 连接超时时间
+ timeout: 10s
+ lettuce:
+ pool:
+ # 连接池最大连接数
+ max-active: 200
+ # 连接池最大阻塞等待时间(使用负值表示没有限制)
+ max-wait: -1ms
+ # 连接池中的最大空闲连接
+ max-idle: 10
+ # 连接池中的最小空闲连接
+ min-idle: 0
+
+
+
+
+
\ No newline at end of file