diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenEventCenter.java b/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenEventCenter.java index 0caca54e..68228dba 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenEventCenter.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenEventCenter.java @@ -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; /** diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListener.java b/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListener.java index 289b7d46..ed0ca42a 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListener.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListener.java @@ -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; /** diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListenerForLog.java b/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListenerForLog.java index 76c888d8..cb770e83 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListenerForLog.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListenerForLog.java @@ -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; diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListenerForSimple.java b/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListenerForSimple.java index 0bce1d3f..f7e30f5c 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListenerForSimple.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListenerForSimple.java @@ -15,7 +15,7 @@ */ package cn.dev33.satoken.listener; -import cn.dev33.satoken.stp.SaLoginParameter; +import cn.dev33.satoken.stp.parameter.SaLoginParameter; /** * Sa-Token 侦听器,默认空实现 diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/session/SaSession.java b/sa-token-core/src/main/java/cn/dev33/satoken/session/SaSession.java index f6851c14..a7eb002d 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/session/SaSession.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/session/SaSession.java @@ -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 / diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/stp/SaLoginConfig.java b/sa-token-core/src/main/java/cn/dev33/satoken/stp/SaLoginConfig.java index 49f5d830..4997f053 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/stp/SaLoginConfig.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/stp/SaLoginConfig.java @@ -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; diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/stp/SaLoginModel.java b/sa-token-core/src/main/java/cn/dev33/satoken/stp/SaLoginModel.java index d54a104d..b62132dd 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/stp/SaLoginModel.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/stp/SaLoginModel.java @@ -15,6 +15,8 @@ */ package cn.dev33.satoken.stp; +import cn.dev33.satoken.stp.parameter.SaLoginParameter; + /** *

请更改为 SaLoginParameter

* 在调用 `StpUtil.login()` 时的 配置参数 Model,决定登录的一些细节行为
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java b/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java index 23fd720a..40a22aee 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java @@ -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 + *

当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5

+ * + * @param tokenValue 指定 token + */ + public void kickoutByTokenValue(String tokenValue) { + kickoutByTokenValue(tokenValue, createSaLogoutParameter()); + } + + /** + * 踢人下线,根据指定 token、注销参数 + *

当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5

+ * + * @param tokenValue 指定 token + * @param logoutParameter 注销参数 + */ + public void kickoutByTokenValue(String tokenValue, SaLogoutParameter logoutParameter) { + _logoutByTokenValue(tokenValue, logoutParameter.setMode(SaLogoutMode.KICKOUT)); + } + + /** + * 顶人下线,根据指定 token + *

当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-4

+ * + * @param tokenValue 指定 token + */ + public void replacedByTokenValue(String tokenValue) { + replacedByTokenValue(tokenValue, createSaLogoutParameter()); + } + + /** + * 顶人下线,根据指定 token、注销参数 + *

当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-4

+ * + * @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 + *

当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5

+ * + * @param loginId 账号id + */ + public void kickout(Object loginId) { + kickout(loginId, createSaLogoutParameter()); + } + + /** + * 踢人下线,根据账号id 和 设备类型 + *

当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5

+ * + * @param loginId 账号id + * @param deviceType 设备类型 (填 null 代表踢出该账号的所有设备类型) + */ + public void kickout(Object loginId, String deviceType) { + kickout(loginId, createSaLogoutParameter().setDeviceType(deviceType)); + } + + /** + * 踢人下线,根据账号id 和 注销参数 + *

当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5

+ * + * @param loginId 账号id + * @param logoutParameter 注销参数 + */ + public void kickout(Object loginId, SaLogoutParameter logoutParameter) { + _logout(loginId, logoutParameter.setMode(SaLogoutMode.KICKOUT)); + } + + /** + * 顶人下线,根据账号id + *

当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-4

+ * + * @param loginId 账号id + */ + public void replaced(Object loginId) { + replaced(loginId, createSaLogoutParameter()); + } + + /** + * 顶人下线,根据账号id 和 设备类型 + *

当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-4

+ * + * @param loginId 账号id + * @param deviceType 设备类型 (填 null 代表顶替该账号的所有设备类型) + */ + public void replaced(Object loginId, String deviceType) { + replaced(loginId, createSaLogoutParameter().setDeviceType(deviceType)); + } + + /** + * 顶人下线,根据账号id 和 注销参数 + *

当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-4

+ * + * @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 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 - *

当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5

- * - * @param loginId 账号id - */ - public void kickout(Object loginId) { - kickout(loginId, null); - } - - /** - * 踢人下线,根据账号id 和 设备类型 - *

当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5

- * - * @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 - *

当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5

- * - * @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 和 设备类型 - *

当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-4

- * - * @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()); + } + // ------------------- 过期方法 ------------------- diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpUtil.java b/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpUtil.java index 42d81650..a879f1d4 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpUtil.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpUtil.java @@ -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 + *

当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5

+ * + * @param tokenValue 指定 token + */ + public static void kickoutByTokenValue(String tokenValue) { + stpLogic.kickoutByTokenValue(tokenValue); + } + + /** + * 踢人下线,根据指定 token、注销参数 + *

当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5

+ * + * @param tokenValue 指定 token + * @param logoutParameter 注销参数 + */ + public static void kickoutByTokenValue(String tokenValue, SaLogoutParameter logoutParameter) { + stpLogic.kickoutByTokenValue(tokenValue, logoutParameter); + } + + /** + * 顶人下线,根据指定 token + *

当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-4

+ * + * @param tokenValue 指定 token + */ + public static void replacedByTokenValue(String tokenValue) { + stpLogic.replacedByTokenValue(tokenValue); + } + + /** + * 顶人下线,根据指定 token、注销参数 + *

当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-4

+ * + * @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 *

当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5

* - * @param loginId 账号id + * @param loginId 账号id */ public static void kickout(Object loginId) { stpLogic.kickout(loginId); @@ -294,13 +367,24 @@ public class StpUtil { } /** - * 踢人下线,根据指定 token + * 踢人下线,根据账号id 和 注销参数 *

当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-5

* - * @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 + *

当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-4

+ * + * @param loginId 账号id + */ + public static void replaced(Object loginId) { + stpLogic.replaced(loginId); } /** @@ -314,6 +398,47 @@ public class StpUtil { stpLogic.replaced(loginId, deviceType); } + /** + * 顶人下线,根据账号id 和 注销参数 + *

当对方再次访问系统时,会抛出 NotLoginException 异常,场景值=-4

+ * + * @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模式下生效) * diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/stp/SaLoginParameter.java b/sa-token-core/src/main/java/cn/dev33/satoken/stp/parameter/SaLoginParameter.java similarity index 88% rename from sa-token-core/src/main/java/cn/dev33/satoken/stp/SaLoginParameter.java rename to sa-token-core/src/main/java/cn/dev33/satoken/stp/parameter/SaLoginParameter.java index d79162f8..c4e4870b 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/stp/SaLoginParameter.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/stp/parameter/SaLoginParameter.java @@ -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,决定登录的一些细节行为
+ * 在调用 `StpUtil.login()` 时的 配置参数对象,决定登录的一些细节行为
* *
  *     	// 例如:在登录时指定 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
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/stp/parameter/SaLogoutParameter.java b/sa-token-core/src/main/java/cn/dev33/satoken/stp/parameter/SaLogoutParameter.java
new file mode 100644
index 00000000..cd03bcf1
--- /dev/null
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/stp/parameter/SaLogoutParameter.java
@@ -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;
+
+/**
+ * 在会话注销时的 配置参数对象,决定注销时的一些细节行为 
+ * + *
+ *     	// 例如:
+ *     	StpUtil.logout(10001, new SaLogoutParameter());
+ * 
+ * + * @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 + + "]"; + } + +} diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/stp/parameter/enums/SaLogoutMode.java b/sa-token-core/src/main/java/cn/dev33/satoken/stp/parameter/enums/SaLogoutMode.java new file mode 100644 index 00000000..add2d509 --- /dev/null +++ b/sa-token-core/src/main/java/cn/dev33/satoken/stp/parameter/enums/SaLogoutMode.java @@ -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; + +} diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/stp/parameter/enums/SaLogoutRange.java b/sa-token-core/src/main/java/cn/dev33/satoken/stp/parameter/enums/SaLogoutRange.java new file mode 100644 index 00000000..7e87a41b --- /dev/null +++ b/sa-token-core/src/main/java/cn/dev33/satoken/stp/parameter/enums/SaLogoutRange.java @@ -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 + +} diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/stp/parameter/enums/SaReplacedMode.java b/sa-token-core/src/main/java/cn/dev33/satoken/stp/parameter/enums/SaReplacedMode.java new file mode 100644 index 00000000..6808f3e8 --- /dev/null +++ b/sa-token-core/src/main/java/cn/dev33/satoken/stp/parameter/enums/SaReplacedMode.java @@ -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 + +} diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/util/SaTokenConsts.java b/sa-token-core/src/main/java/cn/dev33/satoken/util/SaTokenConsts.java index f83ccf30..ca009e75 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/util/SaTokenConsts.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/util/SaTokenConsts.java @@ -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 标记: 在封禁账号时,默认封禁的服务类型 diff --git a/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/satoken/MySaTokenListener.java b/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/satoken/MySaTokenListener.java index 494b516d..811e963b 100644 --- a/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/satoken/MySaTokenListener.java +++ b/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/satoken/MySaTokenListener.java @@ -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 自定义侦听器的实现 diff --git a/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/satoken/StpUserUtil.java b/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/satoken/StpUserUtil.java index f64c77d7..5285729f 100644 --- a/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/satoken/StpUserUtil.java +++ b/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/satoken/StpUserUtil.java @@ -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; diff --git a/sa-token-demo/sa-token-demo-case/src/main/resources/application.yml b/sa-token-demo/sa-token-demo-case/src/main/resources/application.yml index 051ea222..ed89db69 100644 --- a/sa-token-demo/sa-token-demo-case/src/main/resources/application.yml +++ b/sa-token-demo/sa-token-demo-case/src/main/resources/application.yml @@ -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 # 是否输出操作日志 diff --git a/sa-token-demo/sa-token-demo-device-lock/src/main/java/com/pj/test/LoginController.java b/sa-token-demo/sa-token-demo-device-lock/src/main/java/com/pj/test/LoginController.java index db9d53e2..8531eaf6 100644 --- a/sa-token-demo/sa-token-demo-device-lock/src/main/java/com/pj/test/LoginController.java +++ b/sa-token-demo/sa-token-demo-device-lock/src/main/java/com/pj/test/LoginController.java @@ -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; diff --git a/sa-token-demo/sa-token-demo-hutool-timed-cache/src/main/resources/application.yml b/sa-token-demo/sa-token-demo-hutool-timed-cache/src/main/resources/application.yml index 3a2d6f57..1889895e 100644 --- a/sa-token-demo/sa-token-demo-hutool-timed-cache/src/main/resources/application.yml +++ b/sa-token-demo/sa-token-demo-hutool-timed-cache/src/main/resources/application.yml @@ -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 # 是否输出操作日志 diff --git a/sa-token-demo/sa-token-demo-test/pom.xml b/sa-token-demo/sa-token-demo-test/pom.xml index 64ff9c72..0ac983f4 100644 --- a/sa-token-demo/sa-token-demo-test/pom.xml +++ b/sa-token-demo/sa-token-demo-test/pom.xml @@ -60,7 +60,7 @@ sa-token-redis-template ${sa-token.version} - + org.apache.commons 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 index 278da594..82654893 100644 --- 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 @@ -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; diff --git a/sa-token-demo/sa-token-demo-test/src/main/java/com/pj/test/LoginController.java b/sa-token-demo/sa-token-demo-test/src/main/java/com/pj/test/LoginController.java index 36176d48..56529460 100644 --- a/sa-token-demo/sa-token-demo-test/src/main/java/com/pj/test/LoginController.java +++ b/sa-token-demo/sa-token-demo-test/src/main/java/com/pj/test/LoginController.java @@ -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(); } diff --git a/sa-token-demo/sa-token-demo-test/src/main/java/com/pj/test/TestController.java b/sa-token-demo/sa-token-demo-test/src/main/java/com/pj/test/TestController.java index 7852160e..81f1fba6 100644 --- a/sa-token-demo/sa-token-demo-test/src/main/java/com/pj/test/TestController.java +++ b/sa-token-demo/sa-token-demo-test/src/main/java/com/pj/test/TestController.java @@ -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; diff --git a/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForMixin.java b/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForMixin.java index 4a42583c..c21dc90f 100644 --- a/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForMixin.java +++ b/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForMixin.java @@ -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; diff --git a/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForStateless.java b/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForStateless.java index 22f70d2b..dd0136d5 100644 --- a/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForStateless.java +++ b/sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt/StpLogicJwtForStateless.java @@ -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; diff --git a/sa-token-test/sa-token-jwt-test/src/test/java/com/pj/test/JwtForMixinTest.java b/sa-token-test/sa-token-jwt-test/src/test/java/com/pj/test/JwtForMixinTest.java index 63807d69..048fe26f 100644 --- a/sa-token-test/sa-token-jwt-test/src/test/java/com/pj/test/JwtForMixinTest.java +++ b/sa-token-test/sa-token-jwt-test/src/test/java/com/pj/test/JwtForMixinTest.java @@ -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数据 验证 diff --git a/sa-token-test/sa-token-jwt-test/src/test/java/com/pj/test/JwtForSimpleTest.java b/sa-token-test/sa-token-jwt-test/src/test/java/com/pj/test/JwtForSimpleTest.java index c6aaf890..c655b701 100644 --- a/sa-token-test/sa-token-jwt-test/src/test/java/com/pj/test/JwtForSimpleTest.java +++ b/sa-token-test/sa-token-jwt-test/src/test/java/com/pj/test/JwtForSimpleTest.java @@ -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); diff --git a/sa-token-test/sa-token-jwt-test/src/test/java/com/pj/test/JwtForStatelessTest.java b/sa-token-test/sa-token-jwt-test/src/test/java/com/pj/test/JwtForStatelessTest.java index 187cdf83..a9260458 100644 --- a/sa-token-test/sa-token-jwt-test/src/test/java/com/pj/test/JwtForStatelessTest.java +++ b/sa-token-test/sa-token-jwt-test/src/test/java/com/pj/test/JwtForStatelessTest.java @@ -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); // 账号类型 // 时间 diff --git a/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/core/stp/TokenInfoTest.java b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/core/stp/TokenInfoTest.java index a1a9ba36..414eb380 100644 --- a/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/core/stp/TokenInfoTest.java +++ b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/core/stp/TokenInfoTest.java @@ -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); } } diff --git a/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/springboot/BasicsTest.java b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/springboot/BasicsTest.java index b2672ae5..63251d0d 100644 --- a/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/springboot/BasicsTest.java +++ b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/springboot/BasicsTest.java @@ -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 tokenList = StpUtil.getTokenValueListByLoginId(10001); - List tokenList2 = StpUtil.getTokenValueListByLoginId(10001, SaTokenConsts.DEFAULT_LOGIN_DEVICE); + List 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存在