新增部分 TokenSign 相关方法,更方便的操作管理会话

This commit is contained in:
click33
2023-06-07 15:49:04 +08:00
parent b43fa1a1c9
commit f59b1b3885
5 changed files with 142 additions and 68 deletions

View File

@@ -15,20 +15,16 @@
*/
package cn.dev33.satoken.session;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.application.SaSetValueInterface;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.listener.SaTokenEventCenter;
import cn.dev33.satoken.util.SaFoxUtil;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* Session Model会话作用域的读取值对象
*
@@ -277,14 +273,15 @@ public class SaSession implements SaSetValueInterface, Serializable {
* @param device 设备类型,填 null 代表不限设备类型
* @return token签名列表
*/
public List<TokenSign> tokenSignListCopyByDevice(String device) {
public List<TokenSign> getTokenSignListByDevice(String device) {
// 返回全部
if(device == null) {
return tokenSignListCopy();
}
// 返回筛选后的
List<TokenSign> tokenSignList = tokenSignListCopy();
List<TokenSign> list = new ArrayList<>();
for (TokenSign tokenSign : tokenSignListCopy()) {
for (TokenSign tokenSign : tokenSignList) {
if(SaFoxUtil.equals(tokenSign.getDevice(), device)) {
list.add(tokenSign);
}
@@ -292,6 +289,24 @@ public class SaSession implements SaSetValueInterface, Serializable {
return list;
}
/**
* 获取当前 Session 上的所有 token 列表
*
* @param device 设备类型,填 null 代表不限设备类型
* @return 此 loginId 的所有登录 token
*/
public List<String> getTokenValueListByDevice(String device) {
// 遍历解析,按照设备类型进行筛选
List<TokenSign> tokenSignList = tokenSignListCopy();
List<String> tokenValueList = new ArrayList<>();
for (TokenSign tokenSign : tokenSignList) {
if(device == null || tokenSign.getDevice().equals(device)) {
tokenValueList.add(tokenSign.getValue());
}
}
return tokenValueList;
}
/**
* 查找一个 Token 签名
*
@@ -313,13 +328,18 @@ public class SaSession implements SaSetValueInterface, Serializable {
* @param tokenSign Token 签名
*/
public void addTokenSign(TokenSign tokenSign) {
// 如果已经存在于列表中,则无需再次添加
if(getTokenSign(tokenSign.getValue()) != null) {
return;
// 根据 tokenValue 值查重,如果不存在,则添加
TokenSign oldTokenSign = getTokenSign(tokenSign.getValue());
if(oldTokenSign == null) {
tokenSignList.add(tokenSign);
update();
} else {
// 如果存在,则更新
oldTokenSign.setValue(tokenSign.getValue());
oldTokenSign.setDevice(tokenSign.getDevice());
oldTokenSign.setTag(tokenSign.getTag());
update();
}
// 添加并更新
tokenSignList.add(tokenSign);
update();
}
/**
@@ -512,4 +532,18 @@ public class SaSession implements SaSetValueInterface, Serializable {
this.update();
}
//
/**
* 请更换为getTokenSignListByDevice(device)
*
* @param device 设备类型,填 null 代表不限设备类型
* @return token签名列表
*/
@Deprecated
public List<TokenSign> tokenSignListCopyByDevice(String device) {
return getTokenSignListByDevice(device);
}
}

View File

@@ -36,7 +36,6 @@ import cn.dev33.satoken.util.SaFoxUtil;
import cn.dev33.satoken.util.SaTokenConsts;
import cn.dev33.satoken.util.SaValue2Box;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -490,8 +489,8 @@ public class StpLogic {
// 3.1、看看全局配置的 IsShare 参数,配置为 true 才是允许复用旧 token
if(getConfigOfIsShare()) {
// 根据账号id + 设备标识,尝试获取旧的 token
String tokenValue = getTokenValueByLoginId(id, loginModel.getDeviceOrDefault());
// 根据账号id尝试获取旧的 token
String tokenValue = getTokenValueByLoginId(id, null);
// 如果有值,那就直接复用
if(SaFoxUtil.isNotEmpty(tokenValue)) {
@@ -605,7 +604,7 @@ public class StpLogic {
if(session != null) {
// 2、遍历此账号所有从这个 device 设备上登录的客户端,清除相关数据
for (TokenSign tokenSign: session.tokenSignListCopyByDevice(device)) {
for (TokenSign tokenSign: session.getTokenSignListByDevice(device)) {
// 2.1、获取此客户端的 token 值
String tokenValue = tokenSign.getValue();
@@ -652,7 +651,7 @@ public class StpLogic {
}
// 2、获取这个账号指定设备类型下的所有登录客户端
List<TokenSign> list = session.tokenSignListCopyByDevice(device);
List<TokenSign> list = session.getTokenSignListByDevice(device);
// 3、按照登录时间倒叙超过 maxLoginCount 数量的,全部注销掉
for (int i = 0; i < list.size() - maxLoginCount; i++) {
@@ -741,7 +740,7 @@ public class StpLogic {
if(session != null) {
// 2、遍历此账号所有从这个 device 设备上登录的客户端,清除相关数据
for (TokenSign tokenSign: session.tokenSignListCopyByDevice(device)) {
for (TokenSign tokenSign: session.getTokenSignListByDevice(device)) {
// 2.1、获取此客户端的 token 值
String tokenValue = tokenSign.getValue();
@@ -817,7 +816,7 @@ public class StpLogic {
if(session != null) {
// 2、遍历此账号所有从这个 device 设备上登录的客户端,清除相关数据
for (TokenSign tokenSign: session.tokenSignListCopyByDevice(device)) {
for (TokenSign tokenSign: session.getTokenSignListByDevice(device)) {
// 2.1、获取此客户端的 token 值
String tokenValue = tokenSign.getValue();
@@ -859,7 +858,17 @@ public class StpLogic {
return getLoginIdDefaultNull() != null;
}
/**
/**
* 判断指定账号是否已经登录
*
* @return 已登录返回 true未登录返回 false
*/
public boolean isLogin(Object loginId) {
// 判断条件:能否根据 loginId 查询到对应的 tokenSign 值
return getTokenSignListByLoginId(loginId, null).size() > 0;
}
/**
* 检验当前会话是否已经登录,如未登录,则抛出异常
*/
public void checkLogin() {
@@ -1989,15 +1998,26 @@ public class StpLogic {
return Collections.emptyList();
}
// 遍历解析,按照设备类型进行筛选
List<TokenSign> tokenSignList = session.tokenSignListCopy();
List<String> tokenValueList = new ArrayList<>();
for (TokenSign tokenSign : tokenSignList) {
if(device == null || tokenSign.getDevice().equals(device)) {
tokenValueList.add(tokenSign.getValue());
}
// 按照设备类型进行筛选
return session.getTokenValueListByDevice(device);
}
/**
* 获取指定账号 id 指定设备类型端的 tokenSign 集合
*
* @param loginId 账号id
* @param device 设备类型,填 null 代表不限设备类型
* @return 此 loginId 的所有登录 token
*/
public List<TokenSign> getTokenSignListByLoginId(Object loginId, String device) {
// 如果该账号的 Account-Session 为 null说明此账号尚没有客户端在登录此时返回空集合
SaSession session = getSessionByLoginId(loginId, false);
if(session == null) {
return Collections.emptyList();
}
return tokenValueList;
// 按照设备类型进行筛选
return session.getTokenSignListByDevice(device);
}
/**

View File

@@ -19,7 +19,9 @@ import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.fun.SaFunction;
import cn.dev33.satoken.listener.SaTokenEventCenter;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.session.TokenSign;
import java.util.Collections;
import java.util.List;
/**
@@ -314,6 +316,15 @@ public class StpUtil {
return stpLogic.isLogin();
}
/**
* 判断指定账号是否已经登录
*
* @return 已登录返回 true未登录返回 false
*/
public static boolean isLogin(Object loginId) {
return stpLogic.isLogin(loginId);
}
/**
* 检验当前会话是否已经登录,如未登录,则抛出异常
*/
@@ -814,6 +825,17 @@ public class StpUtil {
return stpLogic.getTokenValueListByLoginId(loginId, device);
}
/**
* 获取指定账号 id 指定设备类型端的 tokenSign 集合
*
* @param loginId 账号id
* @param device 设备类型,填 null 代表不限设备类型
* @return 此 loginId 的所有登录 tokenSign
*/
public static List<TokenSign> getTokenSignListByLoginId(Object loginId, String device) {
return stpLogic.getTokenSignListByLoginId(loginId, device);
}
/**
* 返回当前会话的登录设备类型
*

View File

@@ -29,7 +29,6 @@ import cn.dev33.satoken.util.SaTokenConsts;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.function.Function;
/**
* Sa-Token 策略对象
@@ -37,11 +36,11 @@ import java.util.function.Function;
* 此类统一定义框架内的一些关键性逻辑算法,方便开发者进行按需重写,例:
* </p>
* <pre>
// SaStrategy全局单例所有方法都用以下形式重写
SaStrategy.instance.setCreateToken((loginId, loginType) -》 {
// 自定义Token生成的算法
return "xxxx";
});
// SaStrategy全局单例所有方法都用以下形式重写
SaStrategy.instance.setCreateToken((loginId, loginType) -》 {
// 自定义Token生成的算法
return "xxxx";
});
* </pre>
*
* @author click33

View File

@@ -1,6 +1,5 @@
package com.pj.test;
import cn.dev33.satoken.stp.SaLoginConfig;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaFoxUtil;
import cn.dev33.satoken.util.SaResult;
@@ -22,7 +21,7 @@ public class TestController {
// 测试登录 ---- http://localhost:8081/test/login
@RequestMapping("login")
public SaResult login(@RequestParam(defaultValue = "10001") long id) {
StpUtil.login(id, SaLoginConfig.setActiveTimeout(20));
StpUtil.login(id);
return SaResult.ok("登录成功");
}