From fd829c34b9783c065961f8d0737e634fec5d0ba1 Mon Sep 17 00:00:00 2001
From: click33 <2393584716@qq.com>
Date: Thu, 20 Oct 2022 06:14:58 +0800
Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=A4=9A=E8=B4=A6=E5=8F=B7?=
=?UTF-8?q?=E4=BD=93=E7=B3=BB=E6=B7=B7=E5=90=88=E9=89=B4=E6=9D=83=E4=BB=A3?=
=?UTF-8?q?=E7=A0=81=E7=A4=BA=E4=BE=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../main/java/com/pj/satoken/StpUserUtil.java | 1032 +++++++++++++++++
sa-token-doc/up/many-account.md | 38 +
2 files changed, 1070 insertions(+)
create mode 100644 sa-token-demo/sa-token-demo-test/src/main/java/com/pj/satoken/StpUserUtil.java
diff --git a/sa-token-demo/sa-token-demo-test/src/main/java/com/pj/satoken/StpUserUtil.java b/sa-token-demo/sa-token-demo-test/src/main/java/com/pj/satoken/StpUserUtil.java
new file mode 100644
index 00000000..198e2225
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-test/src/main/java/com/pj/satoken/StpUserUtil.java
@@ -0,0 +1,1032 @@
+package com.pj.satoken;
+
+import java.util.List;
+
+import org.springframework.stereotype.Component;
+
+import cn.dev33.satoken.SaManager;
+import cn.dev33.satoken.fun.SaFunction;
+import cn.dev33.satoken.session.SaSession;
+import cn.dev33.satoken.stp.SaLoginModel;
+import cn.dev33.satoken.stp.SaTokenInfo;
+import cn.dev33.satoken.stp.StpLogic;
+
+/**
+ * Sa-Token 权限认证工具类 (User版)
+ * @author kong
+ */
+@Component
+public class StpUserUtil {
+
+ private StpUserUtil() {}
+
+ /**
+ * 账号类型标识
+ */
+ public static final String TYPE = "user";
+
+ /**
+ * 底层的 StpLogic 对象
+ */
+ public static StpLogic stpLogic = new StpLogic(TYPE);
+
+ /**
+ * 获取当前 StpLogic 的账号类型
+ * @return See Note
+ */
+ public static String getLoginType(){
+ return stpLogic.getLoginType();
+ }
+
+ /**
+ * 重置 StpLogic 对象
+ *
1、更改此账户的 StpLogic 对象
+ *
2、put 到全局 StpLogic 集合中
+ *
+ * @param newStpLogic /
+ */
+ public static void setStpLogic(StpLogic newStpLogic) {
+ // 重置此账户的 StpLogic 对象
+ stpLogic = newStpLogic;
+
+ // 添加到全局 StpLogic 集合中
+ // 以便可以通过 SaManager.getStpLogic(type) 的方式来全局获取到这个 StpLogic
+ SaManager.putStpLogic(newStpLogic);
+ }
+
+ /**
+ * 获取 StpLogic 对象
+ * @return /
+ */
+ public static StpLogic getStpLogic() {
+ return stpLogic;
+ }
+
+
+ // ------------------- 获取token 相关 -------------------
+
+ /**
+ * 返回token名称
+ * @return 此StpLogic的token名称
+ */
+ public static String getTokenName() {
+ return stpLogic.getTokenName();
+ }
+
+ /**
+ * 在当前会话写入当前TokenValue
+ * @param tokenValue token值
+ */
+ public static void setTokenValue(String tokenValue){
+ stpLogic.setTokenValue(tokenValue);
+ }
+
+ /**
+ * 在当前会话写入当前TokenValue
+ * @param tokenValue token值
+ * @param cookieTimeout Cookie存活时间(秒)
+ */
+ public static void setTokenValue(String tokenValue, int cookieTimeout){
+ stpLogic.setTokenValue(tokenValue, cookieTimeout);
+ }
+
+ /**
+ * 获取当前TokenValue
+ * @return 当前tokenValue
+ */
+ public static String getTokenValue() {
+ return stpLogic.getTokenValue();
+ }
+
+ /**
+ * 获取当前TokenValue (不裁剪前缀)
+ * @return /
+ */
+ public static String getTokenValueNotCut(){
+ return stpLogic.getTokenValueNotCut();
+ }
+
+ /**
+ * 获取当前会话的Token信息
+ * @return token信息
+ */
+ public static SaTokenInfo getTokenInfo() {
+ return stpLogic.getTokenInfo();
+ }
+
+
+ // ------------------- 登录相关操作 -------------------
+
+ // --- 登录
+
+ /**
+ * 会话登录
+ * @param id 账号id,建议的类型:(long | int | String)
+ */
+ public static void login(Object id) {
+ stpLogic.login(id);
+ }
+
+ /**
+ * 会话登录,并指定登录设备类型
+ * @param id 账号id,建议的类型:(long | int | String)
+ * @param device 设备类型
+ */
+ public static void login(Object id, String device) {
+ stpLogic.login(id, device);
+ }
+
+ /**
+ * 会话登录,并指定是否 [记住我]
+ *
+ * @param id 账号id,建议的类型:(long | int | String)
+ * @param isLastingCookie 是否为持久Cookie
+ */
+ public static void login(Object id, boolean isLastingCookie) {
+ stpLogic.login(id, isLastingCookie);
+ }
+
+ /**
+ * 会话登录,并指定此次登录token的有效期, 单位:秒
+ *
+ * @param id 账号id,建议的类型:(long | int | String)
+ * @param timeout 此次登录token的有效期, 单位:秒 (如未指定,自动取全局配置的timeout值)
+ */
+ public static void login(Object id, long timeout) {
+ stpLogic.login(id, timeout);
+ }
+
+ /**
+ * 会话登录,并指定所有登录参数Model
+ *
+ * @param id 登录id,建议的类型:(long | int | String)
+ * @param loginModel 此次登录的参数Model
+ */
+ public static void login(Object id, SaLoginModel loginModel) {
+ stpLogic.login(id, loginModel);
+ }
+
+ /**
+ * 创建指定账号id的登录会话
+ * @param id 登录id,建议的类型:(long | int | String)
+ * @return 返回会话令牌
+ */
+ public static String createLoginSession(Object id) {
+ return stpLogic.createLoginSession(id);
+ }
+
+ /**
+ * 创建指定账号id的登录会话
+ * @param id 登录id,建议的类型:(long | int | String)
+ * @param loginModel 此次登录的参数Model
+ * @return 返回会话令牌
+ */
+ public static String createLoginSession(Object id, SaLoginModel loginModel) {
+ return stpLogic.createLoginSession(id, loginModel);
+ }
+
+ // --- 注销
+
+ /**
+ * 会话注销
+ */
+ public static void logout() {
+ stpLogic.logout();
+ }
+
+ /**
+ * 会话注销,根据账号id
+ * @param loginId 账号id
+ */
+ public static void logout(Object loginId) {
+ stpLogic.logout(loginId);
+ }
+
+ /**
+ * 会话注销,根据账号id 和 设备类型
+ *
+ * @param loginId 账号id
+ * @param device 设备类型 (填null代表注销所有设备类型)
+ */
+ public static void logout(Object loginId, String device) {
+ stpLogic.logout(loginId, device);
+ }
+
+ /**
+ * 会话注销,根据指定 Token
+ *
+ * @param tokenValue 指定token
+ */
+ public static void logoutByTokenValue(String tokenValue) {
+ stpLogic.logoutByTokenValue(tokenValue);
+ }
+
+ /**
+ * 踢人下线,根据账号id
+ *
当对方再次访问系统时,会抛出NotLoginException异常,场景值=-5
+ * + * @param loginId 账号id + */ + public static void kickout(Object loginId) { + stpLogic.kickout(loginId); + } + + /** + * 踢人下线,根据账号id 和 设备类型 + *当对方再次访问系统时,会抛出NotLoginException异常,场景值=-5
+ * + * @param loginId 账号id + * @param device 设备类型 (填null代表踢出所有设备类型) + */ + public static void kickout(Object loginId, String device) { + stpLogic.kickout(loginId, device); + } + + /** + * 踢人下线,根据指定 Token + *当对方再次访问系统时,会抛出NotLoginException异常,场景值=-5
+ * + * @param tokenValue 指定token + */ + public static void kickoutByTokenValue(String tokenValue) { + stpLogic.kickoutByTokenValue(tokenValue); + } + + /** + * 顶人下线,根据账号id 和 设备类型 + *当对方再次访问系统时,会抛出NotLoginException异常,场景值=-4
+ * + * @param loginId 账号id + * @param device 设备类型 (填null代表顶替所有设备类型) + */ + public static void replaced(Object loginId, String device) { + stpLogic.replaced(loginId, device); + } + + + // 查询相关 + + /** + * 当前会话是否已经登录 + * @return 是否已登录 + */ + public static boolean isLogin() { + return stpLogic.isLogin(); + } + + /** + * 检验当前会话是否已经登录,如未登录,则抛出异常 + */ + public static void checkLogin() { + stpLogic.checkLogin(); + } + + /** + * 获取当前会话账号id, 如果未登录,则抛出异常 + * @return 账号id + */ + public static Object getLoginId() { + return stpLogic.getLoginId(); + } + + /** + * 获取当前会话账号id, 如果未登录,则返回默认值 + * @param在配置为允许并发登录时,此方法只会返回队列的最后一个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 此方法不会直接将此账号id踢下线,如需封禁后立即掉线,请追加调用 StpUtil.logout(id)
+ *
+ * @param loginId 指定账号id
+ * @param time 封禁时间, 单位: 秒 (-1=永久封禁)
+ */
+ public static void disable(Object loginId, long time) {
+ stpLogic.disable(loginId, time);
+ }
+
+ /**
+ * 判断:指定账号是否已被封禁 (true=已被封禁, false=未被封禁)
+ *
+ * @param loginId 账号id
+ * @return /
+ */
+ public static boolean isDisable(Object loginId) {
+ return stpLogic.isDisable(loginId);
+ }
+
+ /**
+ * 校验:指定账号是否已被封禁,如果被封禁则抛出异常
+ * @param loginId 账号id
+ */
+ public static void checkDisable(Object loginId) {
+ stpLogic.checkDisable(loginId);
+ }
+
+ /**
+ * 获取:指定账号剩余封禁时间,单位:秒(-1=永久封禁,-2=未被封禁)
+ * @param loginId 账号id
+ * @return /
+ */
+ public static long getDisableTime(Object loginId) {
+ return stpLogic.getDisableTime(loginId);
+ }
+
+ /**
+ * 解封:指定账号
+ * @param loginId 账号id
+ */
+ public static void untieDisable(Object loginId) {
+ stpLogic.untieDisable(loginId);
+ }
+
+
+ // ------------------- 分类封禁 -------------------
+
+ /**
+ * 封禁:指定账号的指定服务
+ * 此方法不会直接将此账号id踢下线,如需封禁后立即掉线,请追加调用 StpUtil.logout(id)
+ * @param loginId 指定账号id
+ * @param service 指定服务
+ * @param time 封禁时间, 单位: 秒 (-1=永久封禁)
+ */
+ public static void disable(Object loginId, String service, long time) {
+ stpLogic.disable(loginId, service, time);
+ }
+
+ /**
+ * 判断:指定账号的指定服务 是否已被封禁 (true=已被封禁, false=未被封禁)
+ * @param loginId 账号id
+ * @param service 指定服务
+ * @return /
+ */
+ public static boolean isDisable(Object loginId, String service) {
+ return stpLogic.isDisable(loginId, service);
+ }
+
+ /**
+ * 校验:指定账号 指定服务 是否已被封禁,如果被封禁则抛出异常
+ * @param loginId 账号id
+ * @param services 指定服务,可以指定多个
+ */
+ public static void checkDisable(Object loginId, String... services) {
+ stpLogic.checkDisable(loginId, services);
+ }
+
+ /**
+ * 获取:指定账号 指定服务 剩余封禁时间,单位:秒(-1=永久封禁,-2=未被封禁)
+ * @param loginId 账号id
+ * @param service 指定服务
+ * @return see note
+ */
+ public static long getDisableTime(Object loginId, String service) {
+ return stpLogic.getDisableTime(loginId, service);
+ }
+
+ /**
+ * 解封:指定账号、指定服务
+ * @param loginId 账号id
+ * @param services 指定服务,可以指定多个
+ */
+ public static void untieDisable(Object loginId, String... services) {
+ stpLogic.untieDisable(loginId, services);
+ }
+
+
+ // ------------------- 阶梯封禁 -------------------
+
+ /**
+ * 封禁:指定账号,并指定封禁等级
+ * @param loginId 指定账号id
+ * @param level 指定封禁等级
+ * @param time 封禁时间, 单位: 秒 (-1=永久封禁)
+ */
+ public static void disableLevel(Object loginId, int level, long time) {
+ stpLogic.disableLevel(loginId, level, time);
+ }
+
+ /**
+ * 封禁:指定账号的指定服务,并指定封禁等级
+ * @param loginId 指定账号id
+ * @param service 指定封禁服务
+ * @param level 指定封禁等级
+ * @param time 封禁时间, 单位: 秒 (-1=永久封禁)
+ */
+ public static void disableLevel(Object loginId, String service, int level, long time) {
+ stpLogic.disableLevel(loginId, service, level, time);
+ }
+
+ /**
+ * 判断:指定账号是否已被封禁到指定等级
+ *
+ * @param loginId 指定账号id
+ * @param level 指定封禁等级
+ * @return /
+ */
+ public static boolean isDisableLevel(Object loginId, int level) {
+ return stpLogic.isDisableLevel(loginId, level);
+ }
+
+ /**
+ * 判断:指定账号的指定服务,是否已被封禁到指定等级
+ *
+ * @param loginId 指定账号id
+ * @param service 指定封禁服务
+ * @param level 指定封禁等级
+ * @return /
+ */
+ public static boolean isDisableLevel(Object loginId, String service, int level) {
+ return stpLogic.isDisableLevel(loginId, service, level);
+ }
+
+ /**
+ * 校验:指定账号是否已被封禁到指定等级(如果已经达到,则抛出异常)
+ *
+ * @param loginId 指定账号id
+ * @param level 封禁等级 (只有 封禁等级 ≥ 此值 才会抛出异常)
+ */
+ public static void checkDisableLevel(Object loginId, int level) {
+ stpLogic.checkDisableLevel(loginId, level);
+ }
+
+ /**
+ * 校验:指定账号的指定服务,是否已被封禁到指定等级(如果已经达到,则抛出异常)
+ *
+ * @param loginId 指定账号id
+ * @param service 指定封禁服务
+ * @param level 封禁等级 (只有 封禁等级 ≥ 此值 才会抛出异常)
+ */
+ public static void checkDisableLevel(Object loginId, String service, int level) {
+ stpLogic.checkDisableLevel(loginId, service, level);
+ }
+
+ /**
+ * 获取:指定账号被封禁的等级,如果未被封禁则返回-2
+ *
+ * @param loginId 指定账号id
+ * @return /
+ */
+ public static int getDisableLevel(Object loginId) {
+ return stpLogic.getDisableLevel(loginId);
+ }
+
+ /**
+ * 获取:指定账号的 指定服务 被封禁的等级,如果未被封禁则返回-2
+ *
+ * @param loginId 指定账号id
+ * @param service 指定封禁服务
+ * @return /
+ */
+ public static int getDisableLevel(Object loginId, String service) {
+ return stpLogic.getDisableLevel(loginId, service);
+ }
+
+
+ // ------------------- 身份切换 -------------------
+
+ /**
+ * 临时切换身份为指定账号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();
+ }
+
+}
diff --git a/sa-token-doc/up/many-account.md b/sa-token-doc/up/many-account.md
index e69c2b5b..12cb3022 100644
--- a/sa-token-doc/up/many-account.md
+++ b/sa-token-doc/up/many-account.md
@@ -188,6 +188,44 @@ public class StpUserUtil {
}
```
+### 9、多账号体系混合鉴权
+QQ群中经常有小伙伴提问:在多账号体系下,怎么在 SaInterceptor 拦截器中给一个接口登录鉴权?
+
+其实这个问题,主要是靠你的业务需求来决定,以后台 Admin 账号和前台 User 账号为例:
+
+``` java
+// 注册 Sa-Token 拦截器
+@Override
+public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(new SaInterceptor(handle -> {
+
+ // 如果这个接口,要求客户端登录了后台 Admin 账号才能访问:
+ SaRouter.match("/art/getInfo").check(r -> StpUtil.checkLogin());
+
+ // 如果这个接口,要求客户端登录了前台 User 账号才能访问:
+ SaRouter.match("/art/getInfo").check(r -> StpUserUtil.checkLogin());
+
+ // 如果这个接口,要求客户端同时登录 Admin 和 User 账号,才能访问:
+ SaRouter.match("/art/getInfo").check(r -> {
+ StpUtil.checkLogin();
+ StpUserUtil.checkLogin();
+ });
+
+ // 如果这个接口,要求客户端登录 Admin 和 User 账号任意一个,就能访问:
+ SaRouter.match("/art/getInfo").check(r -> {
+ if(StpUtil.isLogin() == false && StpUserUtil.isLogin() == false) {
+ throw new SaTokenException("请登录后再访问接口");
+ }
+ });
+
+ })).addPathPatterns("/**");
+}
+```
+
+
+
+
+
---