mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-04-05 08:37:21 +08:00
feat: 新增 SaLogoutParameter,用于控制注销会话时的各种细节 & 优化注销会话相关 API & SaLoginParameter 新增 replacedMode、overflowLogoutMode & SaTokenConsts.DEFAULT_LOGIN_DEVICE_TYPE 默认值改为 DEF
This commit is contained in:
parent
c7f27e393e
commit
79016e5ffe
@ -22,7 +22,7 @@ import cn.dev33.satoken.annotation.handler.SaAnnotationHandlerInterface;
|
||||
import cn.dev33.satoken.config.SaTokenConfig;
|
||||
import cn.dev33.satoken.error.SaErrorCode;
|
||||
import cn.dev33.satoken.exception.SaTokenException;
|
||||
import cn.dev33.satoken.stp.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
|
||||
/**
|
||||
|
@ -17,7 +17,7 @@ package cn.dev33.satoken.listener;
|
||||
|
||||
import cn.dev33.satoken.annotation.handler.SaAnnotationHandlerInterface;
|
||||
import cn.dev33.satoken.config.SaTokenConfig;
|
||||
import cn.dev33.satoken.stp.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
|
||||
/**
|
||||
|
@ -17,7 +17,7 @@ package cn.dev33.satoken.listener;
|
||||
|
||||
import cn.dev33.satoken.annotation.handler.SaAnnotationHandlerInterface;
|
||||
import cn.dev33.satoken.config.SaTokenConfig;
|
||||
import cn.dev33.satoken.stp.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
*/
|
||||
package cn.dev33.satoken.listener;
|
||||
|
||||
import cn.dev33.satoken.stp.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||
|
||||
/**
|
||||
* Sa-Token 侦听器,默认空实现
|
||||
|
@ -88,6 +88,11 @@ public class SaSession implements SaSetValueInterface, Serializable {
|
||||
*/
|
||||
private String token;
|
||||
|
||||
/**
|
||||
* 当前账号历史总计登录设备数量 (当此 SaSession 属于 Account-Session 时,此值有效)
|
||||
*/
|
||||
private int historyTerminalCount;
|
||||
|
||||
/**
|
||||
* 此 SaSession 的创建时间(13位时间戳)
|
||||
*/
|
||||
@ -330,6 +335,8 @@ public class SaSession implements SaSetValueInterface, Serializable {
|
||||
terminalList.remove(oldTerminal);
|
||||
}
|
||||
// 然后添加新的
|
||||
this.historyTerminalCount++;
|
||||
terminalInfo.setIndex(this.historyTerminalCount);
|
||||
terminalList.add(terminalInfo);
|
||||
update();
|
||||
}
|
||||
@ -347,20 +354,24 @@ public class SaSession implements SaSetValueInterface, Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最大的终端索引值,如无返0
|
||||
* 获取 当前账号历史总计登录设备数量 (当此 SaSession 属于 Account-Session 时,此值有效)
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public int maxTerminalIndex() {
|
||||
int max = 0;
|
||||
for (SaTerminalInfo terminal : terminalListCopy()) {
|
||||
int index = terminal.getIndex();
|
||||
if (index > max) {
|
||||
max = index;
|
||||
}
|
||||
}
|
||||
return max;
|
||||
public int getHistoryTerminalCount() {
|
||||
return this.historyTerminalCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 当前账号历史总计登录设备数量 (当此 SaSession 属于 Account-Session 时,此值有效)
|
||||
*
|
||||
* @param historyTerminalCount /
|
||||
*/
|
||||
public void setHistoryTerminalCount(int historyTerminalCount) {
|
||||
this.historyTerminalCount = historyTerminalCount;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判断指定设备 id 是否为可信任设备
|
||||
* @param deviceId /
|
||||
|
@ -16,6 +16,7 @@
|
||||
package cn.dev33.satoken.stp;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -15,6 +15,8 @@
|
||||
*/
|
||||
package cn.dev33.satoken.stp;
|
||||
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||
|
||||
/**
|
||||
* <h2> 请更改为 SaLoginParameter </h2>
|
||||
* 在调用 `StpUtil.login()` 时的 配置参数 Model,决定登录的一些细节行为 <br>
|
||||
|
@ -31,6 +31,11 @@ import cn.dev33.satoken.listener.SaTokenEventCenter;
|
||||
import cn.dev33.satoken.model.wrapperInfo.SaDisableWrapperInfo;
|
||||
import cn.dev33.satoken.session.SaSession;
|
||||
import cn.dev33.satoken.session.SaTerminalInfo;
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.parameter.SaLogoutParameter;
|
||||
import cn.dev33.satoken.stp.parameter.enums.SaLogoutMode;
|
||||
import cn.dev33.satoken.stp.parameter.enums.SaLogoutRange;
|
||||
import cn.dev33.satoken.stp.parameter.enums.SaReplacedMode;
|
||||
import cn.dev33.satoken.strategy.SaStrategy;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
import cn.dev33.satoken.util.SaTokenConsts;
|
||||
@ -473,7 +478,6 @@ public class StpLogic {
|
||||
|
||||
// 4、在 Account-Session 上记录本次登录的终端信息
|
||||
SaTerminalInfo terminalInfo = new SaTerminalInfo()
|
||||
.setIndex(session.maxTerminalIndex() + 1)
|
||||
.setDeviceType(loginParameter.getDeviceType())
|
||||
.setDeviceId(loginParameter.getDeviceId())
|
||||
.setTokenValue(tokenValue)
|
||||
@ -500,7 +504,7 @@ public class StpLogic {
|
||||
|
||||
// 9、检查此账号会话数量是否超出最大值,如果超过,则按照登录时间顺序,把最开始登录的给注销掉
|
||||
if(loginParameter.getMaxLoginCount() != -1) {
|
||||
logoutByMaxLoginCount(id, session, null, loginParameter.getMaxLoginCount());
|
||||
logoutByMaxLoginCount(id, session, null, loginParameter.getMaxLoginCount(), loginParameter.getOverflowLogoutMode());
|
||||
}
|
||||
|
||||
// 10、一切处理完毕,返回会话凭证 token
|
||||
@ -519,8 +523,12 @@ public class StpLogic {
|
||||
// 1、获取全局配置的 isConcurrent 参数
|
||||
// 如果配置为:不允许一个账号多地同时登录,则需要先将这个账号的历史登录会话标记为:被顶下线
|
||||
if( ! loginParameter.getIsConcurrent()) {
|
||||
// TODO 此处应该加一个配置决定是只顶掉当前设备类型,还是所有类型
|
||||
replaced(id, loginParameter.getDeviceType());
|
||||
if(loginParameter.getReplacedMode() == SaReplacedMode.CURR_DEVICE_TYPE) {
|
||||
replaced(id, loginParameter.getDeviceTypeOrDefault());
|
||||
}
|
||||
if(loginParameter.getReplacedMode() == SaReplacedMode.ALL_DEVICE_TYPE) {
|
||||
replaced(id, createSaLogoutParameter());
|
||||
}
|
||||
}
|
||||
|
||||
// 2、如果调用者预定了要生成的 token,则直接返回这个预定的值,框架无需再操心了
|
||||
@ -612,12 +620,19 @@ public class StpLogic {
|
||||
return tokenValue;
|
||||
}
|
||||
|
||||
// --- 注销
|
||||
|
||||
/**
|
||||
// --- 注销 (根据 token)
|
||||
|
||||
/**
|
||||
* 在当前客户端会话注销
|
||||
*/
|
||||
public void logout() {
|
||||
logout(createSaLogoutParameter());
|
||||
}
|
||||
|
||||
/**
|
||||
* 在当前客户端会话注销,根据注销参数
|
||||
*/
|
||||
public void logout(SaLogoutParameter logoutParameter) {
|
||||
// 1、如果本次请求连 Token 都没有提交,那么它本身也不属于登录状态,此时无需执行任何操作
|
||||
String tokenValue = getTokenValue();
|
||||
if(SaFoxUtil.isEmpty(tokenValue)) {
|
||||
@ -649,67 +664,338 @@ public class StpLogic {
|
||||
storage.delete(SaTokenConsts.TOKEN_ACTIVE_TIMEOUT_CHECKED_KEY);
|
||||
|
||||
// 5、清除这个 token 的其它相关信息
|
||||
logoutByTokenValue(tokenValue);
|
||||
if(logoutParameter.getRange() == SaLogoutRange.TOKEN) {
|
||||
logoutByTokenValue(tokenValue, logoutParameter);
|
||||
} else {
|
||||
Object loginId = getLoginIdByTokenNotThinkFreeze(tokenValue);
|
||||
if(loginId != null) {
|
||||
if(!logoutParameter.getIsKeepFreezeOps() && isFreeze(tokenValue)) {
|
||||
return;
|
||||
}
|
||||
logout(loginId, logoutParameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 会话注销,根据账号id
|
||||
* 注销下线,根据指定 token
|
||||
*
|
||||
* @param loginId 账号id
|
||||
* @param tokenValue 指定 token
|
||||
*/
|
||||
public void logoutByTokenValue(String tokenValue) {
|
||||
logoutByTokenValue(tokenValue, createSaLogoutParameter());
|
||||
}
|
||||
|
||||
/**
|
||||
* 注销下线,根据指定 token、注销参数
|
||||
*
|
||||
* @param tokenValue 指定 token
|
||||
* @param logoutParameter /
|
||||
*/
|
||||
public void logoutByTokenValue(String tokenValue, SaLogoutParameter logoutParameter) {
|
||||
_logoutByTokenValue(tokenValue, logoutParameter.setMode(SaLogoutMode.LOGOUT));
|
||||
}
|
||||
|
||||
/**
|
||||
* 踢人下线,根据指定 token
|
||||
* <p> 当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5 </p>
|
||||
*
|
||||
* @param tokenValue 指定 token
|
||||
*/
|
||||
public void kickoutByTokenValue(String tokenValue) {
|
||||
kickoutByTokenValue(tokenValue, createSaLogoutParameter());
|
||||
}
|
||||
|
||||
/**
|
||||
* 踢人下线,根据指定 token、注销参数
|
||||
* <p> 当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5 </p>
|
||||
*
|
||||
* @param tokenValue 指定 token
|
||||
* @param logoutParameter 注销参数
|
||||
*/
|
||||
public void kickoutByTokenValue(String tokenValue, SaLogoutParameter logoutParameter) {
|
||||
_logoutByTokenValue(tokenValue, logoutParameter.setMode(SaLogoutMode.KICKOUT));
|
||||
}
|
||||
|
||||
/**
|
||||
* 顶人下线,根据指定 token
|
||||
* <p> 当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-4 </p>
|
||||
*
|
||||
* @param tokenValue 指定 token
|
||||
*/
|
||||
public void replacedByTokenValue(String tokenValue) {
|
||||
replacedByTokenValue(tokenValue, createSaLogoutParameter());
|
||||
}
|
||||
|
||||
/**
|
||||
* 顶人下线,根据指定 token、注销参数
|
||||
* <p> 当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-4 </p>
|
||||
*
|
||||
* @param tokenValue 指定 token
|
||||
* @param logoutParameter /
|
||||
*/
|
||||
public void replacedByTokenValue(String tokenValue, SaLogoutParameter logoutParameter) {
|
||||
_logoutByTokenValue(tokenValue, logoutParameter.setMode(SaLogoutMode.REPLACED));
|
||||
}
|
||||
|
||||
/**
|
||||
* [work] 注销下线,根据指定 token 、注销参数
|
||||
*
|
||||
* @param tokenValue 指定 token
|
||||
* @param logoutParameter 注销参数
|
||||
*/
|
||||
public void _logoutByTokenValue(String tokenValue, SaLogoutParameter logoutParameter) {
|
||||
|
||||
// 1、判断一下:如果此 token 映射的是一个无效 loginId,则此处立即返回,不需要再往下处理了
|
||||
// 如果不提前截止,则后续的操作可能会写入意外数据
|
||||
Object loginId = getLoginIdByTokenNotThinkFreeze(tokenValue);
|
||||
if( SaFoxUtil.isEmpty(loginId) ) {
|
||||
return;
|
||||
}
|
||||
if(!logoutParameter.getIsKeepFreezeOps() && isFreeze(tokenValue)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 2、清除这个 token 的最后活跃时间记录
|
||||
if(isOpenCheckActiveTimeout()) {
|
||||
clearLastActive(tokenValue);
|
||||
}
|
||||
|
||||
// 3、清除 Token-Session
|
||||
if( ! logoutParameter.getIsKeepTokenSession()) {
|
||||
deleteTokenSession(tokenValue);
|
||||
}
|
||||
|
||||
// 4、清理或更改 Token 映射
|
||||
// 5、发布事件通知
|
||||
// SaLogoutMode.LOGOUT:注销下线
|
||||
if(logoutParameter.getMode() == SaLogoutMode.LOGOUT) {
|
||||
deleteTokenToIdMapping(tokenValue);
|
||||
SaTokenEventCenter.doLogout(loginType, loginId, tokenValue);
|
||||
}
|
||||
// SaLogoutMode.LOGOUT:踢人下线
|
||||
if(logoutParameter.getMode() == SaLogoutMode.KICKOUT) {
|
||||
updateTokenToIdMapping(tokenValue, NotLoginException.KICK_OUT);
|
||||
SaTokenEventCenter.doKickout(loginType, loginId, tokenValue);
|
||||
}
|
||||
// SaLogoutMode.REPLACED:顶人下线
|
||||
if(logoutParameter.getMode() == SaLogoutMode.REPLACED) {
|
||||
updateTokenToIdMapping(tokenValue, NotLoginException.BE_REPLACED);
|
||||
SaTokenEventCenter.doReplaced(loginType, loginId, tokenValue);
|
||||
}
|
||||
|
||||
// 6、清理这个账号的 Account-Session 上的 terminal 信息,并且尝试注销掉 Account-Session
|
||||
SaSession session = getSessionByLoginId(loginId, false);
|
||||
if(session != null) {
|
||||
session.removeTerminal(tokenValue);
|
||||
session.logoutByTerminalCountToZero();
|
||||
}
|
||||
}
|
||||
|
||||
// --- 注销 (根据 loginId)
|
||||
|
||||
/**
|
||||
* 会话注销,根据账号id
|
||||
*
|
||||
* @param loginId 账号id
|
||||
*/
|
||||
public void logout(Object loginId) {
|
||||
logout(loginId, null);
|
||||
logout(loginId, createSaLogoutParameter());
|
||||
}
|
||||
|
||||
/**
|
||||
* 会话注销,根据账号id 和 设备类型
|
||||
*
|
||||
* @param loginId 账号id
|
||||
*
|
||||
* @param loginId 账号id
|
||||
* @param deviceType 设备类型 (填 null 代表注销该账号的所有设备类型)
|
||||
*/
|
||||
public void logout(Object loginId, String deviceType) {
|
||||
logout(loginId, createSaLogoutParameter().setDeviceType(deviceType));
|
||||
}
|
||||
|
||||
/**
|
||||
* 会话注销,根据账号id 和 注销参数
|
||||
*
|
||||
* @param loginId 账号id
|
||||
* @param logoutParameter 注销参数
|
||||
*/
|
||||
public void logout(Object loginId, SaLogoutParameter logoutParameter) {
|
||||
_logout(loginId, logoutParameter.setMode(SaLogoutMode.LOGOUT));
|
||||
}
|
||||
|
||||
/**
|
||||
* 踢人下线,根据账号id
|
||||
* <p> 当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5 </p>
|
||||
*
|
||||
* @param loginId 账号id
|
||||
*/
|
||||
public void kickout(Object loginId) {
|
||||
kickout(loginId, createSaLogoutParameter());
|
||||
}
|
||||
|
||||
/**
|
||||
* 踢人下线,根据账号id 和 设备类型
|
||||
* <p> 当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5 </p>
|
||||
*
|
||||
* @param loginId 账号id
|
||||
* @param deviceType 设备类型 (填 null 代表踢出该账号的所有设备类型)
|
||||
*/
|
||||
public void kickout(Object loginId, String deviceType) {
|
||||
kickout(loginId, createSaLogoutParameter().setDeviceType(deviceType));
|
||||
}
|
||||
|
||||
/**
|
||||
* 踢人下线,根据账号id 和 注销参数
|
||||
* <p> 当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5 </p>
|
||||
*
|
||||
* @param loginId 账号id
|
||||
* @param logoutParameter 注销参数
|
||||
*/
|
||||
public void kickout(Object loginId, SaLogoutParameter logoutParameter) {
|
||||
_logout(loginId, logoutParameter.setMode(SaLogoutMode.KICKOUT));
|
||||
}
|
||||
|
||||
/**
|
||||
* 顶人下线,根据账号id
|
||||
* <p> 当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-4 </p>
|
||||
*
|
||||
* @param loginId 账号id
|
||||
*/
|
||||
public void replaced(Object loginId) {
|
||||
replaced(loginId, createSaLogoutParameter());
|
||||
}
|
||||
|
||||
/**
|
||||
* 顶人下线,根据账号id 和 设备类型
|
||||
* <p> 当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-4 </p>
|
||||
*
|
||||
* @param loginId 账号id
|
||||
* @param deviceType 设备类型 (填 null 代表顶替该账号的所有设备类型)
|
||||
*/
|
||||
public void replaced(Object loginId, String deviceType) {
|
||||
replaced(loginId, createSaLogoutParameter().setDeviceType(deviceType));
|
||||
}
|
||||
|
||||
/**
|
||||
* 顶人下线,根据账号id 和 注销参数
|
||||
* <p> 当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-4 </p>
|
||||
*
|
||||
* @param loginId 账号id
|
||||
* @param logoutParameter 注销参数
|
||||
*/
|
||||
public void replaced(Object loginId, SaLogoutParameter logoutParameter) {
|
||||
_logout(loginId, logoutParameter.setMode(SaLogoutMode.REPLACED));
|
||||
}
|
||||
|
||||
/**
|
||||
* [work] 会话注销,根据账号id 和 注销参数
|
||||
*
|
||||
* @param loginId 账号id
|
||||
* @param logoutParameter 注销参数
|
||||
*/
|
||||
public void _logout(Object loginId, SaLogoutParameter logoutParameter) {
|
||||
// 1、获取此账号的 Account-Session,上面记录了此账号的所有登录客户端数据
|
||||
SaSession session = getSessionByLoginId(loginId, false);
|
||||
if(session != null) {
|
||||
|
||||
// 2、遍历此账号所有从这个 deviceType 设备类型上登录的客户端,清除相关数据
|
||||
for (SaTerminalInfo terminal: session.getTerminalListByDeviceType(deviceType)) {
|
||||
|
||||
// 2.1、获取此客户端的 token 值
|
||||
String tokenValue = terminal.getTokenValue();
|
||||
|
||||
// 2.2、从 Account-Session 上清除此设备信息
|
||||
session.removeTerminal(tokenValue);
|
||||
|
||||
// 2.3、清除这个 token 的最后活跃时间记录
|
||||
if(isOpenCheckActiveTimeout()) {
|
||||
clearLastActive(tokenValue);
|
||||
}
|
||||
|
||||
// 2.4、清除 token -> id 的映射关系
|
||||
deleteTokenToIdMapping(tokenValue);
|
||||
|
||||
// 2.5、清除这个 token 的 Token-Session 对象
|
||||
deleteTokenSession(tokenValue);
|
||||
|
||||
// 2.6、$$ 发布事件:xx 账号的 xx 客户端注销了
|
||||
SaTokenEventCenter.doLogout(loginType, loginId, tokenValue);
|
||||
// 2、遍历此 SaTerminalInfo 客户端列表,清除相关数据
|
||||
List<SaTerminalInfo> terminalList = session.getTerminalListByDeviceType(logoutParameter.getDeviceType());
|
||||
for (SaTerminalInfo terminal: terminalList) {
|
||||
_removeTerminal(session, terminal, logoutParameter);
|
||||
}
|
||||
|
||||
// 3、如果代码走到这里的时候,此账号已经没有客户端在登录了,则直接注销掉这个 Account-Session
|
||||
session.logoutByTerminalCountToZero();
|
||||
if(logoutParameter.getMode() == SaLogoutMode.REPLACED) {
|
||||
// 因为调用顶替下线时,一般都是在新客户端正在登录,所以此种情况不需要清除该账号的 Account-Session
|
||||
// 如果清除了 Account-Session,将可能导致 Account-Session 被注销后又立刻创建出来,造成不必要的性能浪费
|
||||
} else {
|
||||
session.logoutByTerminalCountToZero();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --- 注销 (会话管理辅助方法)
|
||||
|
||||
/**
|
||||
* 在 Account-Session 上移除 Terminal 信息 (注销下线方式)
|
||||
* @param session /
|
||||
* @param terminal /
|
||||
*/
|
||||
public void removeTerminalByLogout(SaSession session, SaTerminalInfo terminal) {
|
||||
_removeTerminal(session, terminal, createSaLogoutParameter().setMode(SaLogoutMode.LOGOUT));
|
||||
}
|
||||
|
||||
/**
|
||||
* 在 Account-Session 上移除 Terminal 信息 (踢人下线方式)
|
||||
* @param session /
|
||||
* @param terminal /
|
||||
*/
|
||||
public void removeTerminalByKickout(SaSession session, SaTerminalInfo terminal) {
|
||||
_removeTerminal(session, terminal, createSaLogoutParameter().setMode(SaLogoutMode.KICKOUT));
|
||||
}
|
||||
|
||||
/**
|
||||
* 在 Account-Session 上移除 Terminal 信息 (顶人下线方式)
|
||||
* @param session /
|
||||
* @param terminal /
|
||||
*/
|
||||
public void removeTerminalByReplaced(SaSession session, SaTerminalInfo terminal) {
|
||||
_removeTerminal(session, terminal, createSaLogoutParameter().setMode(SaLogoutMode.REPLACED));
|
||||
}
|
||||
|
||||
/**
|
||||
* 在 Account-Session 上移除 Terminal 信息 (内部方法,仅为减少重复代码,外部调用意义不大)
|
||||
* @param session Account-Session
|
||||
* @param terminal 设备信息
|
||||
* @param logoutParameter 注销参数
|
||||
*/
|
||||
public void _removeTerminal(SaSession session, SaTerminalInfo terminal, SaLogoutParameter logoutParameter) {
|
||||
|
||||
Object loginId = session.getLoginId();
|
||||
String tokenValue = terminal.getTokenValue();
|
||||
|
||||
// 1、从 Account-Session 上清除此设备信息
|
||||
session.removeTerminal(tokenValue);
|
||||
|
||||
// 2、清除这个 token 的最后活跃时间记录
|
||||
if(isOpenCheckActiveTimeout()) {
|
||||
clearLastActive(tokenValue);
|
||||
}
|
||||
|
||||
// 3、清除这个 token 的 Token-Session 对象
|
||||
if( ! logoutParameter.getIsKeepTokenSession()) {
|
||||
deleteTokenSession(tokenValue);
|
||||
}
|
||||
|
||||
// 4、清理或更改 Token 映射
|
||||
// 5、发布事件通知
|
||||
// SaLogoutMode.LOGOUT:注销下线
|
||||
if(logoutParameter.getMode() == SaLogoutMode.LOGOUT) {
|
||||
deleteTokenToIdMapping(tokenValue);
|
||||
SaTokenEventCenter.doLogout(loginType, loginId, tokenValue);
|
||||
}
|
||||
// SaLogoutMode.LOGOUT:踢人下线
|
||||
if(logoutParameter.getMode() == SaLogoutMode.KICKOUT) {
|
||||
updateTokenToIdMapping(tokenValue, NotLoginException.KICK_OUT);
|
||||
SaTokenEventCenter.doKickout(loginType, loginId, tokenValue);
|
||||
}
|
||||
// SaLogoutMode.REPLACED:顶人下线
|
||||
if(logoutParameter.getMode() == SaLogoutMode.REPLACED) {
|
||||
updateTokenToIdMapping(tokenValue, NotLoginException.BE_REPLACED);
|
||||
SaTokenEventCenter.doReplaced(loginType, loginId, tokenValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果指定账号 id、设备类型的登录客户端已经超过了指定数量,则按照登录时间顺序,把最开始登录的给注销掉
|
||||
*
|
||||
* @param loginId 账号id
|
||||
*
|
||||
* @param loginId 账号id
|
||||
* @param session 此账号的 Account-Session 对象,可填写 null,框架将自动获取
|
||||
* @param deviceType 设备类型(填 null 代表注销此账号所有设备类型的登录)
|
||||
* @param maxLoginCount 最大登录数量,超过此数量的将被注销
|
||||
* @param logoutMode 超出的客户端将以何种方式被注销
|
||||
*/
|
||||
public void logoutByMaxLoginCount(Object loginId, SaSession session, String deviceType, int maxLoginCount) {
|
||||
public void logoutByMaxLoginCount(Object loginId, SaSession session, String deviceType, int maxLoginCount, SaLogoutMode logoutMode) {
|
||||
|
||||
// 1、如果调用者提供的 Account-Session 对象为空,则我们先手动获取一下
|
||||
if(session == null) {
|
||||
@ -724,196 +1010,14 @@ public class StpLogic {
|
||||
|
||||
// 3、按照登录时间倒叙,超过 maxLoginCount 数量的,全部注销掉
|
||||
for (int i = 0; i < list.size() - maxLoginCount; i++) {
|
||||
|
||||
// 3.1、获取此客户端的 token 值
|
||||
String tokenValue = list.get(i).getTokenValue();
|
||||
|
||||
// 3.2、从 Account-Session 上清除 terminal 信息
|
||||
session.removeTerminal(tokenValue);
|
||||
|
||||
// 3.3、清除这个 token 的最后活跃时间记录
|
||||
if(isOpenCheckActiveTimeout()) {
|
||||
clearLastActive(tokenValue);
|
||||
}
|
||||
|
||||
// 3.4、清除 token -> id 的映射关系
|
||||
deleteTokenToIdMapping(tokenValue);
|
||||
|
||||
// 3.5、清除这个 token 的 Token-Session 对象
|
||||
deleteTokenSession(tokenValue);
|
||||
|
||||
// 3.6、$$ 发布事件:xx 账号的 xx 客户端注销了
|
||||
SaTokenEventCenter.doLogout(loginType, loginId, tokenValue);
|
||||
_removeTerminal(session, list.get(i), createSaLogoutParameter().setMode(logoutMode));
|
||||
}
|
||||
|
||||
// 4、如果代码走到这里的时候,此账号已经没有客户端在登录了,则直接注销掉这个 Account-Session
|
||||
session.logoutByTerminalCountToZero();
|
||||
}
|
||||
|
||||
/**
|
||||
* 会话注销,根据指定 Token
|
||||
*
|
||||
* @param tokenValue 指定 token
|
||||
*/
|
||||
public void logoutByTokenValue(String tokenValue) {
|
||||
// 1、清除这个 token 的最后活跃时间记录
|
||||
if(isOpenCheckActiveTimeout()) {
|
||||
clearLastActive(tokenValue);
|
||||
}
|
||||
|
||||
// 2、清除这个 token 的 Token-Session 对象
|
||||
deleteTokenSession(tokenValue);
|
||||
|
||||
// 3、清除 token -> id 的映射关系
|
||||
String loginId = getLoginIdNotHandle(tokenValue);
|
||||
if(loginId != null) {
|
||||
deleteTokenToIdMapping(tokenValue);
|
||||
}
|
||||
|
||||
// 4、判断一下:如果此 token 映射的是一个无效 loginId,则此处立即返回,不需要再往下处理了
|
||||
if( ! isValidLoginId(loginId) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 5、$$ 发布事件:某某账号的某某 token 注销下线了
|
||||
SaTokenEventCenter.doLogout(loginType, loginId, tokenValue);
|
||||
|
||||
// 6、清理这个账号的 Account-Session 上的 terminal 信息,并且尝试注销掉 Account-Session
|
||||
SaSession session = getSessionByLoginId(loginId, false);
|
||||
if(session != null) {
|
||||
session.removeTerminal(tokenValue);
|
||||
session.logoutByTerminalCountToZero();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 踢人下线,根据账号id
|
||||
* <p> 当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5 </p>
|
||||
*
|
||||
* @param loginId 账号id
|
||||
*/
|
||||
public void kickout(Object loginId) {
|
||||
kickout(loginId, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 踢人下线,根据账号id 和 设备类型
|
||||
* <p> 当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5 </p>
|
||||
*
|
||||
* @param loginId 账号id
|
||||
* @param deviceType 设备类型 (填 null 代表踢出该账号的所有设备类型)
|
||||
*/
|
||||
public void kickout(Object loginId, String deviceType) {
|
||||
// 1、获取此账号的 Account-Session,上面记录了此账号的所有登录客户端数据
|
||||
SaSession session = getSessionByLoginId(loginId, false);
|
||||
if(session != null) {
|
||||
|
||||
// 2、遍历此账号所有从这个 deviceType 设备上登录的客户端,清除相关数据
|
||||
for (SaTerminalInfo terminal: session.getTerminalListByDeviceType(deviceType)) {
|
||||
|
||||
// 2.1、获取此客户端的 token 值
|
||||
String tokenValue = terminal.getTokenValue();
|
||||
|
||||
// 2.2、从 Account-Session 上清除 terminal 信息
|
||||
session.removeTerminal(tokenValue);
|
||||
|
||||
// 2.3、清除这个 token 的最后活跃时间记录
|
||||
if(isOpenCheckActiveTimeout()) {
|
||||
clearLastActive(tokenValue);
|
||||
}
|
||||
|
||||
// 2.4、将此 token 标记为:已被踢下线
|
||||
updateTokenToIdMapping(tokenValue, NotLoginException.KICK_OUT);
|
||||
|
||||
// 2.5、清除 Token-Session
|
||||
deleteTokenSession(tokenValue);
|
||||
|
||||
// 2.6、$$ 发布事件:xx 账号的 xx 客户端被踢下线了
|
||||
SaTokenEventCenter.doKickout(loginType, loginId, tokenValue);
|
||||
}
|
||||
|
||||
// 3、如果代码走到这里的时候,此账号已经没有客户端在登录了,则直接注销掉这个 Account-Session
|
||||
session.logoutByTerminalCountToZero();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 踢人下线,根据指定 token
|
||||
* <p> 当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5 </p>
|
||||
*
|
||||
* @param tokenValue 指定 token
|
||||
*/
|
||||
public void kickoutByTokenValue(String tokenValue) {
|
||||
// 1、清除这个 token 的最后活跃时间记录
|
||||
if(isOpenCheckActiveTimeout()) {
|
||||
clearLastActive(tokenValue);
|
||||
}
|
||||
|
||||
// 2、清除 Token-Session
|
||||
deleteTokenSession(tokenValue);
|
||||
|
||||
// 3、判断一下:如果此 token 映射的是一个无效 loginId,则此处立即返回,不需要再往下处理了
|
||||
String loginId = getLoginIdNotHandle(tokenValue);
|
||||
if( ! isValidLoginId(loginId) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 4、将此 token 标记为:已被踢下线
|
||||
updateTokenToIdMapping(tokenValue, NotLoginException.KICK_OUT);
|
||||
|
||||
// 5、$$. 发布事件:某某 token 被踢下线了
|
||||
SaTokenEventCenter.doKickout(loginType, loginId, tokenValue);
|
||||
|
||||
// 6、清理这个账号的 Account-Session 上的 terminal 信息,并且尝试注销掉 Account-Session
|
||||
SaSession session = getSessionByLoginId(loginId, false);
|
||||
if(session != null) {
|
||||
session.removeTerminal(tokenValue);
|
||||
session.logoutByTerminalCountToZero();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 顶人下线,根据账号id 和 设备类型
|
||||
* <p> 当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-4 </p>
|
||||
*
|
||||
* @param loginId 账号id
|
||||
* @param deviceType 设备类型 (填 null 代表顶替该账号的所有设备类型)
|
||||
*/
|
||||
public void replaced(Object loginId, String deviceType) {
|
||||
// 1、获取此账号的 Account-Session,上面记录了此账号的所有登录客户端数据
|
||||
SaSession session = getSessionByLoginId(loginId, false);
|
||||
if(session != null) {
|
||||
|
||||
// 2、遍历此账号所有从这个 deviceType 设备上登录的客户端,清除相关数据
|
||||
for (SaTerminalInfo ter: session.getTerminalListByDeviceType(deviceType)) {
|
||||
|
||||
// 2.1、获取此客户端的 token 值
|
||||
String tokenValue = ter.getTokenValue();
|
||||
|
||||
// 2.2、从 Account-Session 上清除 terminal 信息
|
||||
session.removeTerminal(tokenValue);
|
||||
|
||||
// 2.3、清除这个 token 的最后活跃时间记录
|
||||
if(isOpenCheckActiveTimeout()) {
|
||||
clearLastActive(tokenValue);
|
||||
}
|
||||
|
||||
// 2.4、将此 token 标记为:已被顶下线
|
||||
updateTokenToIdMapping(tokenValue, NotLoginException.BE_REPLACED);
|
||||
|
||||
// 2.5、清除 Token-Session 对象
|
||||
deleteTokenSession(tokenValue);
|
||||
|
||||
// 2.6、$$ 发布事件:xx 账号的 xx 客户端注销了
|
||||
SaTokenEventCenter.doReplaced(loginType, loginId, tokenValue);
|
||||
}
|
||||
|
||||
// 3、因为调用顶替下线时,一般都是在新客户端正在登录,所以此处不需要清除该账号的 Account-Session
|
||||
// 如果此处清除了 Account-Session,将可能导致 Account-Session 被注销后又立刻创建出来,造成不必要的性能浪费
|
||||
// session.logoutByTerminalCountToZero();
|
||||
}
|
||||
}
|
||||
|
||||
// ---- 会话查询
|
||||
|
||||
/**
|
||||
@ -1092,28 +1196,49 @@ public class StpLogic {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定 token 对应的账号id,如果未登录,则返回 null
|
||||
* 获取指定 token 对应的账号id,如果 token 无效或 token 处于被踢、被顶、被冻结等状态,则返回 null
|
||||
*
|
||||
* @param tokenValue token
|
||||
* @return 账号id
|
||||
*/
|
||||
public Object getLoginIdByToken(String tokenValue) {
|
||||
|
||||
// 1、如果提供的 token 为空,则直接返回 null
|
||||
if(SaFoxUtil.isEmpty(tokenValue)) {
|
||||
return null;
|
||||
}
|
||||
Object loginId = getLoginIdByTokenNotThinkFreeze(tokenValue);
|
||||
|
||||
// 2、查找此 token 对应的 loginId,如果找不到或找的到但属于无效值,则返回 null
|
||||
String loginId = getLoginIdNotHandle(tokenValue);
|
||||
if( ! isValidLoginId(loginId) ) {
|
||||
return null;
|
||||
}
|
||||
if( SaFoxUtil.isNotEmpty(loginId) ) {
|
||||
// 如果 token 已被冻结,也返回 null
|
||||
long activeTimeout = getTokenActiveTimeoutByToken(tokenValue);
|
||||
if(activeTimeout == SaTokenDao.NOT_VALUE_EXPIRE) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 3、返回
|
||||
return loginId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定 token 对应的账号id,如果 token 无效或 token 处于被踢、被顶等状态 (不考虑被冻结),则返回 null
|
||||
*
|
||||
* @param tokenValue token
|
||||
* @return 账号id
|
||||
*/
|
||||
public Object getLoginIdByTokenNotThinkFreeze(String tokenValue) {
|
||||
|
||||
// 1、如果提供的 token 为空,则直接返回 null
|
||||
if(SaFoxUtil.isEmpty(tokenValue)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 2、查找此 token 对应的 loginId,如果找不到或找的到但属于无效值,则返回 null
|
||||
String loginId = getLoginIdNotHandle(tokenValue);
|
||||
if( ! isValidLoginId(loginId) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 3、返回
|
||||
return loginId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定 token 对应的账号id (不做任何特殊处理)
|
||||
*
|
||||
@ -1530,24 +1655,36 @@ public class StpLogic {
|
||||
protected void clearLastActive(String tokenValue) {
|
||||
getSaTokenDao().delete(splicingKeyLastActiveTime(tokenValue));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* 判断指定 token 是否已被冻结
|
||||
*
|
||||
* @param tokenValue 指定 token
|
||||
*/
|
||||
public boolean isFreeze(String tokenValue) {
|
||||
|
||||
// 1、获取这个 token 的剩余活跃有效期
|
||||
long activeTimeout = getTokenActiveTimeoutByToken(tokenValue);
|
||||
|
||||
// 2、值为 -1 代表此 token 已经被设置永不冻结
|
||||
if(activeTimeout == SaTokenDao.NEVER_EXPIRE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3、值为 -2 代表已被冻结
|
||||
if(activeTimeout == SaTokenDao.NOT_VALUE_EXPIRE) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查指定 token 是否已被冻结,如果是则抛出异常
|
||||
*
|
||||
* @param tokenValue 指定 token
|
||||
*/
|
||||
public void checkActiveTimeout(String tokenValue) {
|
||||
|
||||
// 1、获取这个 token 的剩余活跃有效期
|
||||
long activeTimeout = getTokenActiveTimeoutByToken(tokenValue);
|
||||
|
||||
// 2、值为 -1 代表此 token 已经被设置永不冻结,无须继续验证
|
||||
if(activeTimeout == SaTokenDao.NEVER_EXPIRE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 3、值为 -2 代表已被冻结,此时需要抛出异常
|
||||
if(activeTimeout == SaTokenDao.NOT_VALUE_EXPIRE) {
|
||||
if (isFreeze(tokenValue)) {
|
||||
throw NotLoginException.newInstance(loginType, TOKEN_FREEZE, TOKEN_FREEZE_MESSAGE, tokenValue).setCode(SaErrorCode.CODE_11016);
|
||||
}
|
||||
}
|
||||
@ -2929,6 +3066,15 @@ public class StpLogic {
|
||||
return new SaLoginParameter(getConfigOrGlobal());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据当前配置对象创建一个 SaLogoutParameter 对象
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public SaLogoutParameter createSaLogoutParameter() {
|
||||
return new SaLogoutParameter(getConfigOrGlobal());
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ------------------- 过期方法 -------------------
|
||||
|
@ -20,6 +20,8 @@ import cn.dev33.satoken.fun.SaFunction;
|
||||
import cn.dev33.satoken.listener.SaTokenEventCenter;
|
||||
import cn.dev33.satoken.session.SaSession;
|
||||
import cn.dev33.satoken.session.SaTerminalInfo;
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.parameter.SaLogoutParameter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -235,7 +237,7 @@ public class StpUtil {
|
||||
return stpLogic.getOrCreateLoginSession(id);
|
||||
}
|
||||
|
||||
// --- 注销
|
||||
// --- 注销 (根据 token)
|
||||
|
||||
/**
|
||||
* 在当前客户端会话注销
|
||||
@ -245,7 +247,77 @@ public class StpUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 会话注销,根据账号id
|
||||
* 在当前客户端会话注销,根据注销参数
|
||||
*/
|
||||
public static void logout(SaLogoutParameter logoutParameter) {
|
||||
stpLogic.logout(logoutParameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注销下线,根据指定 token
|
||||
*
|
||||
* @param tokenValue 指定 token
|
||||
*/
|
||||
public static void logoutByTokenValue(String tokenValue) {
|
||||
stpLogic.logoutByTokenValue(tokenValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注销下线,根据指定 token、注销参数
|
||||
*
|
||||
* @param tokenValue 指定 token
|
||||
* @param logoutParameter /
|
||||
*/
|
||||
public static void logoutByTokenValue(String tokenValue, SaLogoutParameter logoutParameter) {
|
||||
stpLogic.logoutByTokenValue(tokenValue, logoutParameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 踢人下线,根据指定 token
|
||||
* <p> 当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5 </p>
|
||||
*
|
||||
* @param tokenValue 指定 token
|
||||
*/
|
||||
public static void kickoutByTokenValue(String tokenValue) {
|
||||
stpLogic.kickoutByTokenValue(tokenValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 踢人下线,根据指定 token、注销参数
|
||||
* <p> 当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5 </p>
|
||||
*
|
||||
* @param tokenValue 指定 token
|
||||
* @param logoutParameter 注销参数
|
||||
*/
|
||||
public static void kickoutByTokenValue(String tokenValue, SaLogoutParameter logoutParameter) {
|
||||
stpLogic.kickoutByTokenValue(tokenValue, logoutParameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 顶人下线,根据指定 token
|
||||
* <p> 当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-4 </p>
|
||||
*
|
||||
* @param tokenValue 指定 token
|
||||
*/
|
||||
public static void replacedByTokenValue(String tokenValue) {
|
||||
stpLogic.replacedByTokenValue(tokenValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 顶人下线,根据指定 token、注销参数
|
||||
* <p> 当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-4 </p>
|
||||
*
|
||||
* @param tokenValue 指定 token
|
||||
* @param logoutParameter /
|
||||
*/
|
||||
public static void replacedByTokenValue(String tokenValue, SaLogoutParameter logoutParameter) {
|
||||
stpLogic.replacedByTokenValue(tokenValue, logoutParameter);
|
||||
}
|
||||
|
||||
// --- 注销 (根据 loginId)
|
||||
|
||||
/**
|
||||
* 会话注销,根据账号id
|
||||
*
|
||||
* @param loginId 账号id
|
||||
*/
|
||||
@ -256,7 +328,7 @@ public class StpUtil {
|
||||
/**
|
||||
* 会话注销,根据账号id 和 设备类型
|
||||
*
|
||||
* @param loginId 账号id
|
||||
* @param loginId 账号id
|
||||
* @param deviceType 设备类型 (填 null 代表注销该账号的所有设备类型)
|
||||
*/
|
||||
public static void logout(Object loginId, String deviceType) {
|
||||
@ -264,19 +336,20 @@ public class StpUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 会话注销,根据指定 Token
|
||||
* 会话注销,根据账号id 和 注销参数
|
||||
*
|
||||
* @param tokenValue 指定 token
|
||||
* @param loginId 账号id
|
||||
* @param logoutParameter 注销参数
|
||||
*/
|
||||
public static void logoutByTokenValue(String tokenValue) {
|
||||
stpLogic.logoutByTokenValue(tokenValue);
|
||||
public static void logout(Object loginId, SaLogoutParameter logoutParameter) {
|
||||
stpLogic.logout(loginId, logoutParameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 踢人下线,根据账号id
|
||||
* 踢人下线,根据账号id
|
||||
* <p> 当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5 </p>
|
||||
*
|
||||
* @param loginId 账号id
|
||||
* @param loginId 账号id
|
||||
*/
|
||||
public static void kickout(Object loginId) {
|
||||
stpLogic.kickout(loginId);
|
||||
@ -294,13 +367,24 @@ public class StpUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 踢人下线,根据指定 token
|
||||
* 踢人下线,根据账号id 和 注销参数
|
||||
* <p> 当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5 </p>
|
||||
*
|
||||
* @param tokenValue 指定 token
|
||||
* @param loginId 账号id
|
||||
* @param logoutParameter 注销参数
|
||||
*/
|
||||
public static void kickoutByTokenValue(String tokenValue) {
|
||||
stpLogic.kickoutByTokenValue(tokenValue);
|
||||
public static void kickout(Object loginId, SaLogoutParameter logoutParameter) {
|
||||
stpLogic.kickout(loginId, logoutParameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 顶人下线,根据账号id
|
||||
* <p> 当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-4 </p>
|
||||
*
|
||||
* @param loginId 账号id
|
||||
*/
|
||||
public static void replaced(Object loginId) {
|
||||
stpLogic.replaced(loginId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -314,6 +398,47 @@ public class StpUtil {
|
||||
stpLogic.replaced(loginId, deviceType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 顶人下线,根据账号id 和 注销参数
|
||||
* <p> 当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-4 </p>
|
||||
*
|
||||
* @param loginId 账号id
|
||||
* @param logoutParameter 注销参数
|
||||
*/
|
||||
public static void replaced(Object loginId, SaLogoutParameter logoutParameter) {
|
||||
stpLogic.replaced(loginId, logoutParameter);
|
||||
}
|
||||
|
||||
// --- 注销 (会话管理辅助方法)
|
||||
|
||||
/**
|
||||
* 在 Account-Session 上移除 Terminal 信息 (注销下线方式)
|
||||
* @param session /
|
||||
* @param terminal /
|
||||
*/
|
||||
public static void removeTerminalByLogout(SaSession session, SaTerminalInfo terminal) {
|
||||
stpLogic.removeTerminalByLogout(session, terminal);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在 Account-Session 上移除 Terminal 信息 (踢人下线方式)
|
||||
* @param session /
|
||||
* @param terminal /
|
||||
*/
|
||||
public static void removeTerminalByKickout(SaSession session, SaTerminalInfo terminal) {
|
||||
stpLogic.removeTerminalByKickout(session, terminal);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在 Account-Session 上移除 Terminal 信息 (顶人下线方式)
|
||||
* @param session /
|
||||
* @param terminal /
|
||||
*/
|
||||
public static void removeTerminalByReplaced(SaSession session, SaTerminalInfo terminal) {
|
||||
stpLogic.removeTerminalByReplaced(session, terminal);
|
||||
}
|
||||
|
||||
|
||||
// 会话查询
|
||||
|
||||
/**
|
||||
@ -398,7 +523,7 @@ public class StpUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定 token 对应的账号id,如果未登录,则返回 null
|
||||
* 获取指定 token 对应的账号id,如果 token 无效或 token 处于被踢、被顶、被冻结等状态,则返回 null
|
||||
*
|
||||
* @param tokenValue token
|
||||
* @return 账号id
|
||||
@ -407,6 +532,16 @@ public class StpUtil {
|
||||
return stpLogic.getLoginIdByToken(tokenValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定 token 对应的账号id,如果 token 无效或 token 处于被踢、被顶等状态 (不考虑被冻结),则返回 null
|
||||
*
|
||||
* @param tokenValue token
|
||||
* @return 账号id
|
||||
*/
|
||||
public Object getLoginIdByTokenNotThinkFreeze(String tokenValue) {
|
||||
return stpLogic.getLoginIdByTokenNotThinkFreeze(tokenValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前 Token 的扩展信息(此函数只在jwt模式下生效)
|
||||
*
|
||||
|
@ -13,18 +13,20 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.dev33.satoken.stp;
|
||||
package cn.dev33.satoken.stp.parameter;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.config.SaTokenConfig;
|
||||
import cn.dev33.satoken.dao.SaTokenDao;
|
||||
import cn.dev33.satoken.stp.parameter.enums.SaLogoutMode;
|
||||
import cn.dev33.satoken.stp.parameter.enums.SaReplacedMode;
|
||||
import cn.dev33.satoken.util.SaTokenConsts;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 在调用 `StpUtil.login()` 时的 配置参数 Model,决定登录的一些细节行为 <br>
|
||||
* 在调用 `StpUtil.login()` 时的 配置参数对象,决定登录的一些细节行为 <br>
|
||||
*
|
||||
* <pre>
|
||||
* // 例如:在登录时指定 token 有效期为七天,代码如下:
|
||||
@ -48,6 +50,16 @@ public class SaLoginParameter {
|
||||
*/
|
||||
private String deviceId;
|
||||
|
||||
/**
|
||||
* 顶人下线的范围
|
||||
*/
|
||||
private SaReplacedMode replacedMode = SaReplacedMode.CURR_DEVICE_TYPE;
|
||||
|
||||
/**
|
||||
* 溢出 maxLoginCount 的客户端,将以何种方式注销下线
|
||||
*/
|
||||
private SaLogoutMode overflowLogoutMode = SaLogoutMode.LOGOUT;
|
||||
|
||||
/**
|
||||
* 扩展信息(只在 jwt 模式下生效)
|
||||
*/
|
||||
@ -123,7 +135,7 @@ public class SaLoginParameter {
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaLoginParameter setDefaultValues(SaTokenConfig config) {
|
||||
this.deviceType = SaTokenConsts.DEFAULT_LOGIN_DEVICE;
|
||||
this.deviceType = SaTokenConsts.DEFAULT_LOGIN_DEVICE_TYPE;
|
||||
this.timeout = config.getTimeout();
|
||||
this.isConcurrent = config.getIsConcurrent();
|
||||
this.isShare = config.getIsShare();
|
||||
@ -220,9 +232,9 @@ public class SaLoginParameter {
|
||||
/**
|
||||
* @return 获取device参数,如果为null,则返回默认值
|
||||
*/
|
||||
public String getDeviceOrDefault() {
|
||||
public String getDeviceTypeOrDefault() {
|
||||
if(deviceType == null) {
|
||||
return SaTokenConsts.DEFAULT_LOGIN_DEVICE;
|
||||
return SaTokenConsts.DEFAULT_LOGIN_DEVICE_TYPE;
|
||||
}
|
||||
return deviceType;
|
||||
}
|
||||
@ -274,6 +286,45 @@ public class SaLoginParameter {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 顶人下线的范围
|
||||
*
|
||||
* @return replacedMode 顶人下线的范围
|
||||
*/
|
||||
public SaReplacedMode getReplacedMode() {
|
||||
return this.replacedMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 顶人下线的范围
|
||||
*
|
||||
* @param replacedMode /
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaLoginParameter setReplacedMode(SaReplacedMode replacedMode) {
|
||||
this.replacedMode = replacedMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 溢出 maxLoginCount 的客户端,将以何种方式注销下线
|
||||
*
|
||||
* @return overflowLogoutMode /
|
||||
*/
|
||||
public SaLogoutMode getOverflowLogoutMode() {
|
||||
return this.overflowLogoutMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 溢出 maxLoginCount 的客户端,将以何种方式注销下线
|
||||
*
|
||||
* @param overflowLogoutMode /
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaLoginParameter setOverflowLogoutMode(SaLogoutMode overflowLogoutMode) {
|
||||
this.overflowLogoutMode = overflowLogoutMode;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* @return 是否为持久Cookie(临时Cookie在浏览器关闭时会自动删除,持久Cookie在重新打开后依然存在)
|
||||
*/
|
||||
@ -462,6 +513,8 @@ public class SaLoginParameter {
|
||||
return "SaLoginParameter ["
|
||||
+ "deviceType=" + deviceType
|
||||
+ ", deviceId=" + deviceId
|
||||
+ ", replacedMode=" + replacedMode
|
||||
+ ", overflowLogoutMode=" + overflowLogoutMode
|
||||
+ ", isLastingCookie=" + isLastingCookie
|
||||
+ ", timeout=" + timeout
|
||||
+ ", activeTimeout=" + activeTimeout
|
@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Copyright 2020-2099 sa-token.cc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.dev33.satoken.stp.parameter;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.config.SaTokenConfig;
|
||||
import cn.dev33.satoken.stp.parameter.enums.SaLogoutMode;
|
||||
import cn.dev33.satoken.stp.parameter.enums.SaLogoutRange;
|
||||
|
||||
/**
|
||||
* 在会话注销时的 配置参数对象,决定注销时的一些细节行为 <br>
|
||||
*
|
||||
* <pre>
|
||||
* // 例如:
|
||||
* StpUtil.logout(10001, new SaLogoutParameter());
|
||||
* </pre>
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.41.0
|
||||
*/
|
||||
public class SaLogoutParameter {
|
||||
|
||||
/**
|
||||
* 是否保留 Token-Session
|
||||
*/
|
||||
private Boolean isKeepTokenSession = false;
|
||||
|
||||
/**
|
||||
* 如果 token 已被冻结,是否保留其操作权 (是否允许此 token 调用注销API)
|
||||
*/
|
||||
private Boolean isKeepFreezeOps = false;
|
||||
|
||||
/**
|
||||
* 设备类型 (如果不指定,则默认注销所有客户端)
|
||||
*/
|
||||
private String deviceType;
|
||||
|
||||
/**
|
||||
* 注销类型
|
||||
*/
|
||||
private SaLogoutMode mode = SaLogoutMode.LOGOUT;
|
||||
|
||||
/**
|
||||
* 注销范围 (此参数只在调用 StpUtil.logout(new SaLogoutParameter()) 时有效)
|
||||
*/
|
||||
private SaLogoutRange range = SaLogoutRange.TOKEN;
|
||||
|
||||
|
||||
// ------ 附加方法
|
||||
|
||||
public SaLogoutParameter() {
|
||||
this(SaManager.getConfig());
|
||||
}
|
||||
public SaLogoutParameter(SaTokenConfig config) {
|
||||
setDefaultValues(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 SaTokenConfig 对象初始化默认值
|
||||
*
|
||||
* @param config 使用的配置对象
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaLogoutParameter setDefaultValues(SaTokenConfig config) {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 静态方法获取一个 SaLoginParameter 对象
|
||||
* @return SaLoginParameter 对象
|
||||
*/
|
||||
public static SaLogoutParameter create() {
|
||||
return new SaLogoutParameter(SaManager.getConfig());
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---------------- get set
|
||||
|
||||
/**
|
||||
* @return 是否保留 Token-Session
|
||||
*/
|
||||
public Boolean getIsKeepTokenSession() {
|
||||
return isKeepTokenSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param isKeepTokenSession 是否保留 Token-Session
|
||||
*
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaLogoutParameter setIsKeepTokenSession(Boolean isKeepTokenSession) {
|
||||
this.isKeepTokenSession = isKeepTokenSession;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 如果 token 已被冻结,是否保留其操作权 (是否允许此 token 调用注销API)
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public Boolean getIsKeepFreezeOps() {
|
||||
return this.isKeepFreezeOps;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 如果 token 已被冻结,是否保留其操作权 (是否允许此 token 调用注销API)
|
||||
*
|
||||
* @param isKeepFreezeOps /
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaLogoutParameter setIsKeepFreezeOps(Boolean isKeepFreezeOps) {
|
||||
this.isKeepFreezeOps = isKeepFreezeOps;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* 获取 设备类型 (如果不指定,则默认注销所有客户端)
|
||||
*
|
||||
* @return deviceType /
|
||||
*/
|
||||
public String getDeviceType() {
|
||||
return this.deviceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 设备类型 (如果不指定,则默认注销所有客户端)
|
||||
*
|
||||
* @param deviceType /
|
||||
* @return /
|
||||
*/
|
||||
public SaLogoutParameter setDeviceType(String deviceType) {
|
||||
this.deviceType = deviceType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 注销类型
|
||||
*
|
||||
* @return logoutMode 注销类型
|
||||
*/
|
||||
public SaLogoutMode getMode() {
|
||||
return this.mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 注销类型
|
||||
*
|
||||
* @param mode 注销类型
|
||||
* @return /
|
||||
*/
|
||||
public SaLogoutParameter setMode(SaLogoutMode mode) {
|
||||
this.mode = mode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 注销范围 (此参数只在调用 StpUtil.logout(new SaLogoutParameter()) 时有效)
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public SaLogoutRange getRange() {
|
||||
return this.range;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 注销范围 (此参数只在调用 StpUtil.logout(new SaLogoutParameter()) 时有效)
|
||||
*
|
||||
* @param range /
|
||||
* @return /
|
||||
*/
|
||||
public SaLogoutParameter setRange(SaLogoutRange range) {
|
||||
this.range = range;
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* toString
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SaLoginParameter ["
|
||||
+ "deviceType=" + deviceType
|
||||
+ ", isKeepTokenSession=" + isKeepTokenSession
|
||||
+ ", isKeepFreezeOps=" + isKeepFreezeOps
|
||||
+ ", mode=" + mode
|
||||
+ ", range=" + range
|
||||
+ "]";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2020-2099 sa-token.cc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.dev33.satoken.stp.parameter.enums;
|
||||
|
||||
/**
|
||||
* SaLogoutMode: 注销模式
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.41.0
|
||||
*/
|
||||
public enum SaLogoutMode {
|
||||
|
||||
/**
|
||||
* 注销下线
|
||||
*/
|
||||
LOGOUT,
|
||||
|
||||
/**
|
||||
* 踢人下线
|
||||
*/
|
||||
KICKOUT,
|
||||
|
||||
/**
|
||||
* 顶人下线
|
||||
*/
|
||||
REPLACED;
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2020-2099 sa-token.cc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.dev33.satoken.stp.parameter.enums;
|
||||
|
||||
/**
|
||||
* SaLogoutMode: 注销范围
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.41.0
|
||||
*/
|
||||
public enum SaLogoutRange {
|
||||
|
||||
/**
|
||||
* token 范围:只注销提供的 token 指向的会话
|
||||
*/
|
||||
TOKEN,
|
||||
|
||||
/**
|
||||
* 账号范围:注销 token 指向的 loginId 会话
|
||||
*/
|
||||
ACCOUNT
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2020-2099 sa-token.cc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.dev33.satoken.stp.parameter.enums;
|
||||
|
||||
/**
|
||||
* 顶人下线的范围
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.41.0
|
||||
*/
|
||||
public enum SaReplacedMode {
|
||||
|
||||
/**
|
||||
* 当前指定的设备类型端
|
||||
*/
|
||||
CURR_DEVICE_TYPE,
|
||||
|
||||
/**
|
||||
* 所有设备类型端
|
||||
*/
|
||||
ALL_DEVICE_TYPE
|
||||
|
||||
}
|
@ -74,7 +74,7 @@ public class SaTokenConsts {
|
||||
/**
|
||||
* 常量 key 标记: 在登录时,默认使用的设备类型
|
||||
*/
|
||||
public static final String DEFAULT_LOGIN_DEVICE = "default-device";
|
||||
public static final String DEFAULT_LOGIN_DEVICE_TYPE = "DEF";
|
||||
|
||||
/**
|
||||
* 常量 key 标记: 在封禁账号时,默认封禁的服务类型
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.pj.satoken;
|
||||
|
||||
import cn.dev33.satoken.listener.SaTokenListener;
|
||||
import cn.dev33.satoken.stp.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||
|
||||
/**
|
||||
* Sa-Token 自定义侦听器的实现
|
||||
|
@ -5,7 +5,7 @@ import cn.dev33.satoken.fun.SaFunction;
|
||||
import cn.dev33.satoken.listener.SaTokenEventCenter;
|
||||
import cn.dev33.satoken.session.SaSession;
|
||||
import cn.dev33.satoken.session.SaTerminalInfo;
|
||||
import cn.dev33.satoken.stp.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.SaTokenInfo;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
|
||||
|
@ -13,7 +13,7 @@ sa-token:
|
||||
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||
is-concurrent: true
|
||||
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||
is-share: true
|
||||
is-share: false
|
||||
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||
token-style: uuid
|
||||
# 是否输出操作日志
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.pj.test;
|
||||
|
||||
import cn.dev33.satoken.stp.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
import com.pj.util.DeviceLockCheckUtil;
|
||||
|
@ -13,7 +13,7 @@ sa-token:
|
||||
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||
is-concurrent: true
|
||||
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||
is-share: true
|
||||
is-share: false
|
||||
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||
token-style: uuid
|
||||
# 是否输出操作日志
|
||||
|
@ -60,7 +60,7 @@
|
||||
<artifactId>sa-token-redis-template</artifactId>
|
||||
<version>${sa-token.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 提供Redis连接池 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
|
@ -4,7 +4,7 @@ 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.stp.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.SaTokenInfo;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.pj.test;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
@ -20,6 +21,7 @@ public class LoginController {
|
||||
// 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对
|
||||
if("zhang".equals(name) && "123456".equals(pwd)) {
|
||||
StpUtil.login(10001);
|
||||
StpUtil.getTokenSession();
|
||||
return SaResult.ok("登录成功");
|
||||
}
|
||||
return SaResult.error("登录失败");
|
||||
@ -47,7 +49,7 @@ public class LoginController {
|
||||
// 测试注销 ---- http://localhost:8081/acc/logout
|
||||
@RequestMapping("logout")
|
||||
public SaResult logout() {
|
||||
StpUtil.logout();
|
||||
StpUtil.login(10001, SaLoginParameter.create().setIsConcurrent(false));
|
||||
return SaResult.ok();
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ import cn.dev33.satoken.annotation.SaCheckHttpDigest;
|
||||
import cn.dev33.satoken.annotation.SaCheckSign;
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import cn.dev33.satoken.spring.SpringMVCUtil;
|
||||
import cn.dev33.satoken.stp.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
|
@ -23,7 +23,7 @@ import cn.dev33.satoken.exception.SaTokenException;
|
||||
import cn.dev33.satoken.jwt.error.SaJwtErrorCode;
|
||||
import cn.dev33.satoken.jwt.exception.SaJwtException;
|
||||
import cn.dev33.satoken.session.SaSession;
|
||||
import cn.dev33.satoken.stp.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.SaTokenInfo;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
|
@ -22,7 +22,7 @@ import cn.dev33.satoken.exception.NotLoginException;
|
||||
import cn.dev33.satoken.jwt.error.SaJwtErrorCode;
|
||||
import cn.dev33.satoken.jwt.exception.SaJwtException;
|
||||
import cn.dev33.satoken.listener.SaTokenEventCenter;
|
||||
import cn.dev33.satoken.stp.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.SaTokenInfo;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
|
@ -59,13 +59,13 @@ public class JwtForMixinTest {
|
||||
Assertions.assertTrue(StpUtil.isLogin());
|
||||
Assertions.assertNotNull(token); // token不为null
|
||||
Assertions.assertEquals(StpUtil.getLoginIdAsLong(), 10001); // loginId=10001
|
||||
Assertions.assertEquals(StpUtil.getLoginDevice(), SaTokenConsts.DEFAULT_LOGIN_DEVICE); // 登录设备类型
|
||||
Assertions.assertEquals(StpUtil.getLoginDevice(), SaTokenConsts.DEFAULT_LOGIN_DEVICE_TYPE); // 登录设备类型
|
||||
|
||||
// token 验证
|
||||
JWT jwt = JWT.of(token);
|
||||
JSONObject payloads = jwt.getPayloads();
|
||||
Assertions.assertEquals(payloads.getStr(SaJwtUtil.LOGIN_ID), "10001"); // 账号
|
||||
Assertions.assertEquals(payloads.getStr(SaJwtUtil.DEVICE_TYPE), SaTokenConsts.DEFAULT_LOGIN_DEVICE); // 登录设备类型
|
||||
Assertions.assertEquals(payloads.getStr(SaJwtUtil.DEVICE_TYPE), SaTokenConsts.DEFAULT_LOGIN_DEVICE_TYPE); // 登录设备类型
|
||||
Assertions.assertEquals(payloads.getStr(SaJwtUtil.LOGIN_TYPE), StpUtil.TYPE); // 账号类型
|
||||
|
||||
// db数据 验证
|
||||
|
@ -54,7 +54,7 @@ public class JwtForSimpleTest {
|
||||
Assertions.assertTrue(StpUtil.isLogin());
|
||||
Assertions.assertNotNull(token); // token不为null
|
||||
Assertions.assertEquals(StpUtil.getLoginIdAsLong(), 10001); // loginId=10001
|
||||
Assertions.assertEquals(StpUtil.getLoginDevice(), SaTokenConsts.DEFAULT_LOGIN_DEVICE); // 登录设备类型
|
||||
Assertions.assertEquals(StpUtil.getLoginDevice(), SaTokenConsts.DEFAULT_LOGIN_DEVICE_TYPE); // 登录设备类型
|
||||
|
||||
// token 验证
|
||||
JWT jwt = JWT.of(token);
|
||||
|
@ -55,13 +55,13 @@ public class JwtForStatelessTest {
|
||||
Assertions.assertTrue(StpUtil.isLogin());
|
||||
Assertions.assertNotNull(token); // token不为null
|
||||
Assertions.assertEquals(StpUtil.getLoginIdAsLong(), 10001); // loginId=10001
|
||||
Assertions.assertEquals(StpUtil.getLoginDevice(), SaTokenConsts.DEFAULT_LOGIN_DEVICE); // 登录设备类型
|
||||
Assertions.assertEquals(StpUtil.getLoginDevice(), SaTokenConsts.DEFAULT_LOGIN_DEVICE_TYPE); // 登录设备类型
|
||||
|
||||
// token 验证
|
||||
JWT jwt = JWT.of(token);
|
||||
JSONObject payloads = jwt.getPayloads();
|
||||
Assertions.assertEquals(payloads.getStr(SaJwtUtil.LOGIN_ID), "10001"); // 账号
|
||||
Assertions.assertEquals(payloads.getStr(SaJwtUtil.DEVICE_TYPE), SaTokenConsts.DEFAULT_LOGIN_DEVICE); // 登录设备类型
|
||||
Assertions.assertEquals(payloads.getStr(SaJwtUtil.DEVICE_TYPE), SaTokenConsts.DEFAULT_LOGIN_DEVICE_TYPE); // 登录设备类型
|
||||
Assertions.assertEquals(payloads.getStr(SaJwtUtil.LOGIN_TYPE), StpUtil.TYPE); // 账号类型
|
||||
|
||||
// 时间
|
||||
|
@ -15,7 +15,7 @@
|
||||
*/
|
||||
package cn.dev33.satoken.core.stp;
|
||||
|
||||
import cn.dev33.satoken.stp.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.SaTokenInfo;
|
||||
import cn.dev33.satoken.util.SaTokenConsts;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
@ -83,7 +83,7 @@ public class TokenInfoTest {
|
||||
.create()
|
||||
.setTimeout(-1);
|
||||
Assertions.assertEquals(loginParameter.getCookieTimeout(), Integer.MAX_VALUE);
|
||||
Assertions.assertEquals(loginParameter.getDeviceOrDefault(), SaTokenConsts.DEFAULT_LOGIN_DEVICE);
|
||||
Assertions.assertEquals(loginParameter.getDeviceTypeOrDefault(), SaTokenConsts.DEFAULT_LOGIN_DEVICE_TYPE);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ import cn.dev33.satoken.session.SaSession;
|
||||
import cn.dev33.satoken.spring.SpringMVCUtil;
|
||||
import cn.dev33.satoken.spring.pathmatch.SaPathMatcherHolder;
|
||||
import cn.dev33.satoken.stp.SaLoginConfig;
|
||||
import cn.dev33.satoken.stp.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.dev33.satoken.util.SaTokenConsts;
|
||||
@ -102,11 +102,11 @@ public class BasicsTest {
|
||||
Assertions.assertNotNull(token);
|
||||
Assertions.assertEquals(token, StpUtil.getTokenValueNotCut());
|
||||
Assertions.assertEquals(token, StpUtil.getTokenValueByLoginId(10001));
|
||||
Assertions.assertEquals(token, StpUtil.getTokenValueByLoginId(10001, SaTokenConsts.DEFAULT_LOGIN_DEVICE));
|
||||
Assertions.assertEquals(token, StpUtil.getTokenValueByLoginId(10001, SaTokenConsts.DEFAULT_LOGIN_DEVICE_TYPE));
|
||||
|
||||
// token 队列
|
||||
List<String> tokenList = StpUtil.getTokenValueListByLoginId(10001);
|
||||
List<String> tokenList2 = StpUtil.getTokenValueListByLoginId(10001, SaTokenConsts.DEFAULT_LOGIN_DEVICE);
|
||||
List<String> tokenList2 = StpUtil.getTokenValueListByLoginId(10001, SaTokenConsts.DEFAULT_LOGIN_DEVICE_TYPE);
|
||||
Assertions.assertEquals(token, tokenList.get(tokenList.size() - 1));
|
||||
Assertions.assertEquals(token, tokenList2.get(tokenList.size() - 1));
|
||||
|
||||
@ -119,7 +119,7 @@ public class BasicsTest {
|
||||
Assertions.assertEquals(StpUtil.getLoginIdAsString(), "10001"); // loginId=10001
|
||||
Assertions.assertEquals(StpUtil.getLoginId(), "10001"); // loginId=10001
|
||||
Assertions.assertEquals(StpUtil.getLoginIdDefaultNull(), "10001"); // loginId=10001
|
||||
Assertions.assertEquals(StpUtil.getLoginDevice(), SaTokenConsts.DEFAULT_LOGIN_DEVICE); // 登录设备类型
|
||||
Assertions.assertEquals(StpUtil.getLoginDevice(), SaTokenConsts.DEFAULT_LOGIN_DEVICE_TYPE); // 登录设备类型
|
||||
|
||||
// db数据 验证
|
||||
// token存在
|
||||
|
Loading…
Reference in New Issue
Block a user