refactor: 重构 TokenSign -> SaTerminalInfo

This commit is contained in:
click33 2025-03-03 16:09:35 +08:00
parent 42fbb0dde8
commit 25fcd80eb6
25 changed files with 654 additions and 521 deletions

View File

@ -234,135 +234,131 @@ public class SaSession implements SaSetValueInterface, Serializable {
}
// ----------------------- TokenSign 相关
// ----------------------- SaTerminalInfo 相关
/**
* Session 绑定的 Token 签名列表
* 登录终端信息列表
*/
private List<TokenSign> tokenSignList = new Vector<>();
private List<SaTerminalInfo> terminalList = new Vector<>();
/**
* 写入 Session 绑定的 Token 签名列表
* @param tokenSignList Token 签名列表
* 写入登录终端信息列表
* @param terminalList /
*/
public void setTokenSignList(List<TokenSign> tokenSignList) {
this.tokenSignList = tokenSignList;
public void setTerminalList(List<SaTerminalInfo> terminalList) {
this.terminalList = terminalList;
}
/**
* 获取 Session 绑定的 Token 签名列表
* 获取登录终端信息列表
*
* @return Token 签名列表
* @return /
*/
public List<TokenSign> getTokenSignList() {
return tokenSignList;
public List<SaTerminalInfo> getTerminalList() {
return terminalList;
}
/**
* 获取 Token 签名列表 的拷贝副本
* 获取 登录终端信息列表 (拷贝副本)
*
* @return token签名列表
* @return /
*/
public List<TokenSign> tokenSignListCopy() {
return new ArrayList<>(tokenSignList);
public List<SaTerminalInfo> terminalListCopy() {
return new ArrayList<>(terminalList);
}
/**
* 返回 Token 签名列表 的拷贝副本根据 device 筛选
* 获取 登录终端信息列表 (拷贝副本)根据 deviceType 筛选
*
* @param device 设备类型 null 代表不限设备类型
* @return token签名列表
* @param deviceType 设备类型 null 代表不限设备类型
* @return /
*/
public List<TokenSign> getTokenSignListByDevice(String device) {
public List<SaTerminalInfo> getTerminalListByDeviceType(String deviceType) {
// 返回全部
if(device == null) {
return tokenSignListCopy();
if(deviceType == null) {
return terminalListCopy();
}
// 返回筛选后的
List<TokenSign> tokenSignList = tokenSignListCopy();
List<TokenSign> list = new ArrayList<>();
for (TokenSign tokenSign : tokenSignList) {
if(SaFoxUtil.equals(tokenSign.getDevice(), device)) {
list.add(tokenSign);
List<SaTerminalInfo> copyList = terminalListCopy();
List<SaTerminalInfo> newList = new ArrayList<>();
for (SaTerminalInfo terminal : copyList) {
if(SaFoxUtil.equals(terminal.getDeviceType(), deviceType)) {
newList.add(terminal);
}
}
return list;
return newList;
}
/**
* 获取当前 Session 上的所有 token 列表
* 获取 登录终端 token 列表
*
* @param device 设备类型 null 代表不限设备类型
* @param deviceType 设备类型 null 代表不限设备类型
* @return loginId 的所有登录 token
*/
public List<String> getTokenValueListByDevice(String device) {
// 遍历解析按照设备类型进行筛选
List<TokenSign> tokenSignList = tokenSignListCopy();
public List<String> getTokenValueListByDeviceType(String deviceType) {
List<String> tokenValueList = new ArrayList<>();
for (TokenSign tokenSign : tokenSignList) {
if(device == null || tokenSign.getDevice().equals(device)) {
tokenValueList.add(tokenSign.getValue());
}
for (SaTerminalInfo terminal : getTerminalListByDeviceType(deviceType)) {
tokenValueList.add(terminal.getTokenValue());
}
return tokenValueList;
}
/**
* 查找一个 Token 签名
* 查找一个终端信息根据 tokenValue
*
* @param tokenValue token值
* @return 查找到的 TokenSign
* @param tokenValue /
* @return /
*/
public TokenSign getTokenSign(String tokenValue) {
for (TokenSign tokenSign : tokenSignListCopy()) {
if (SaFoxUtil.equals(tokenSign.getValue(), tokenValue)) {
return tokenSign;
public SaTerminalInfo getTerminal(String tokenValue) {
for (SaTerminalInfo terminal : terminalListCopy()) {
if (SaFoxUtil.equals(terminal.getTokenValue(), tokenValue)) {
return terminal;
}
}
return null;
}
/**
* 添加一个 Token 签名
* 添加一个终端信息
*
* @param tokenSign Token 签名
* @param terminalInfo /
*/
public void addTokenSign(TokenSign tokenSign) {
// 根据 tokenValue 值查重如果不存在则添加
TokenSign oldTokenSign = getTokenSign(tokenSign.getValue());
if(oldTokenSign == null) {
tokenSignList.add(tokenSign);
update();
} else {
// 如果存在则更新
oldTokenSign.setValue(tokenSign.getValue());
oldTokenSign.setDevice(tokenSign.getDevice());
oldTokenSign.setTag(tokenSign.getTag());
public void addTerminal(SaTerminalInfo terminalInfo) {
// 根据 tokenValue 值查重如果存在旧的则先删除
SaTerminalInfo oldTerminal = getTerminal(terminalInfo.getTokenValue());
if(oldTerminal != null) {
terminalList.remove(oldTerminal);
}
// 然后添加新的
terminalList.add(terminalInfo);
update();
}
/**
* 移除一个终端信息
*
* @param tokenValue token值
*/
public void removeTerminal(String tokenValue) {
SaTerminalInfo terminalInfo = getTerminal(tokenValue);
if (terminalList.remove(terminalInfo)) {
update();
}
}
/**
* 添加一个 Token 签名
*
* @param tokenValue token值
* @param device 设备类型
* 获取最大的终端索引值如无返0
* @return /
*/
@Deprecated
public void addTokenSign(String tokenValue, String device) {
addTokenSign(new TokenSign(tokenValue, device, null));
}
/**
* 移除一个 Token 签名
*
* @param tokenValue token值
*/
public void removeTokenSign(String tokenValue) {
TokenSign tokenSign = getTokenSign(tokenValue);
if (tokenSignList.remove(tokenSign)) {
update();
public int maxTerminalIndex() {
int max = 0;
for (SaTerminalInfo terminal : terminalListCopy()) {
int index = terminal.getIndex();
if (index > max) {
max = index;
}
}
return max;
}
@ -382,9 +378,9 @@ public class SaSession implements SaSetValueInterface, Serializable {
SaTokenEventCenter.doLogoutSession(id);
}
/** 当Session上的tokenSign数量为零时,注销会话 */
public void logoutByTokenSignCountToZero() {
if (tokenSignList.size() == 0) {
/** 当 Session 上的 SaTerminalInfo 数量为零时,注销会话 */
public void logoutByTerminalCountToZero() {
if (terminalList.isEmpty()) {
logout();
}
}
@ -546,16 +542,4 @@ public class SaSession implements SaSetValueInterface, Serializable {
//
/**
* 请更换为getTokenSignListByDevice(device)
*
* @param device 设备类型 null 代表不限设备类型
* @return token签名列表
*/
@Deprecated
public List<TokenSign> tokenSignListCopyByDevice(String device) {
return getTokenSignListByDevice(device);
}
}

View File

@ -0,0 +1,225 @@
/*
* 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.session;
import java.io.Serializable;
/**
* 登录设备终端信息 Model
*
* @author click33
* @since 1.41.0
*/
public class SaTerminalInfo implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1406115065849845073L;
/**
* 登录会话索引值 (该账号第几个登录的设备, 1 开始)
*/
private int index;
/**
* Token
*/
private String tokenValue;
/**
* 所属设备类型例如PCWEBHDMOBILEAPP
*/
private String deviceType;
/**
* 登录设备唯一标识例如kQwIOrYvnXmSDkwEiFngrKidMcdrgKorXmSDkwEiFngrKidM
*/
private String deviceId;
/**
* 此次登录的自定义挂载数据
*/
private Object tag;
/**
* 创建时间
*/
private long createTime;
/**
* 构建一个
*/
public SaTerminalInfo() {
}
/**
* 构建一个
*
* @param index 登录会话索引值 (该账号第几个登录的设备)
* @param tokenValue Token
* @param deviceType 所属设备类型
* @param tag 此客户端登录的挂载数据
*/
public SaTerminalInfo(int index, String tokenValue, String deviceType, Object tag) {
this.index = index;
this.tokenValue = tokenValue;
this.deviceType = deviceType;
this.tag = tag;
this.createTime = System.currentTimeMillis();
}
/**
* 获取 登录会话索引值 (该账号第几个登录的设备)
*
* @return index 登录会话索引值 (该账号第几个登录的设备)
*/
public int getIndex() {
return this.index;
}
/**
* 设置 登录会话索引值 (该账号第几个登录的设备)
*
* @param index 登录会话索引值 (该账号第几个登录的设备)
* @return 对象自身
*/
public SaTerminalInfo setIndex(int index) {
this.index = index;
return this;
}
/**
* @return Token
*/
public String getTokenValue() {
return tokenValue;
}
/**
* 写入 Token
*
* @param tokenValue /
* @return 对象自身
*/
public SaTerminalInfo setTokenValue(String tokenValue) {
this.tokenValue = tokenValue;
return this;
}
/**
* @return 所属设备类型
*/
public String getDeviceType() {
return deviceType;
}
/**
* 写入所属设备类型
*
* @param deviceType /
* @return 对象自身
*/
public SaTerminalInfo setDeviceType(String deviceType) {
this.deviceType = deviceType;
return this;
}
/**
* 获取 登录设备唯一标识
*
* @return deviceId 登录设备唯一标识
*/
public String getDeviceId() {
return this.deviceId;
}
/**
* 设置 登录设备唯一标识例如kQwIOrYvnXmSDkwEiFngrKidMcdrgKorXmSDkwEiFngrKidM
*
* @param deviceId 登录设备唯一标识例如kQwIOrYvnXmSDkwEiFngrKidMcdrgKorXmSDkwEiFngrKidM
* @return 对象自身
*/
public SaTerminalInfo setDeviceId(String deviceId) {
this.deviceId = deviceId;
return this;
}
/**
* 获取 此客户端登录的挂载数据
*
* @return /
*/
public Object getTag() {
return this.tag;
}
/**
* 设置 此客户端登录的挂载数据
*
* @param tag /
* @return 对象自身
*/
public SaTerminalInfo setTag(Object tag) {
this.tag = tag;
return this;
}
/**
* 获取 创建时间
*
* @return createTime 创建时间
*/
public long getCreateTime() {
return this.createTime;
}
/**
* 设置 创建时间
*
* @param createTime 创建时间
* @return 对象自身
*/
public SaTerminalInfo setCreateTime(long createTime) {
this.createTime = createTime;
return this;
}
//
@Override
public String toString() {
return "TokenSign [" +
"index=" + index +
", tokenValue=" + tokenValue +
", deviceType=" + deviceType +
", deviceId=" + deviceId +
", tag=" + tag +
", createTime=" + createTime +
"]";
}
/*
* Expand in the future:
* deviceName 登录设备端名称一般为浏览器名称
* systemName 登录设备操作系统名称
* loginIp 登录IP地址
* address 登录设备地理位置
* loginTime 登录时间
*/
}

View File

@ -1,131 +0,0 @@
/*
* 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.session;
import java.io.Serializable;
/**
* Token 签名 Model
*
* <p> 挂在到 SaSession 上的 Token 签名一般情况下一个 TokenSign 代表一个登录的会话</p>
*
* @author click33
* @since 1.8.0
*/
public class TokenSign implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1406115065849845073L;
/**
* Token
*/
private String value;
/**
* 所属设备类型
*/
private String device;
/**
* 此客户端登录的挂载数据
*/
private Object tag;
/**
* 构建一个
*/
public TokenSign() {
}
/**
* 构建一个
*
* @param value Token
* @param device 所属设备类型
* @param tag 此客户端登录的挂载数据
*/
public TokenSign(String value, String device, Object tag) {
this.value = value;
this.device = device;
this.tag = tag;
}
/**
* @return Token
*/
public String getValue() {
return value;
}
/**
* @return 所属设备类型
*/
public String getDevice() {
return device;
}
/**
* 写入 Token
*
* @param value /
* @return 对象自身
*/
public TokenSign setValue(String value) {
this.value = value;
return this;
}
/**
* 写入所属设备类型
*
* @param device /
* @return 对象自身
*/
public TokenSign setDevice(String device) {
this.device = device;
return this;
}
/**
* 获取 此客户端登录的挂载数据
*
* @return /
*/
public Object getTag() {
return this.tag;
}
/**
* 设置 此客户端登录的挂载数据
*
* @param tag /
* @return 对象自身
*/
public TokenSign setTag(Object tag) {
this.tag = tag;
return this;
}
//
@Override
public String toString() {
return "TokenSign [value=" + value + ", device=" + device + ", tag=" + tag + "]";
}
}

View File

@ -46,7 +46,7 @@ public class SaLoginConfig {
* @return 登录参数 Model
*/
public static SaLoginParameter setDevice(String device) {
return create().setDevice(device);
return create().setDeviceType(device);
}
/**
@ -114,7 +114,7 @@ public class SaLoginConfig {
* @return 登录参数 Model
*/
public static SaLoginParameter setTokenSignTag(Object tokenSignTag) {
return create().setTokenSignTag(tokenSignTag);
return create().setTerminalTag(tokenSignTag);
}
/**

View File

@ -41,7 +41,12 @@ public class SaLoginParameter {
/**
* 此次登录的客户端设备类型
*/
private String device;
private String deviceType;
/**
* 此次登录的客户端设备id
*/
private String deviceId;
/**
* 扩展信息只在 jwt 模式下生效
@ -54,9 +59,9 @@ public class SaLoginParameter {
private String token;
/**
* 本次登录挂载到 TokenSign 数据
* 本次登录挂载到 SaTerminalInfo 的自定义数据
*/
private Object tokenSignTag;
private Object terminalTag;
// --------- 覆盖性参数
@ -118,7 +123,7 @@ public class SaLoginParameter {
* @return 对象自身
*/
public SaLoginParameter setDefaultValues(SaTokenConfig config) {
this.device = SaTokenConsts.DEFAULT_LOGIN_DEVICE;
this.deviceType = SaTokenConsts.DEFAULT_LOGIN_DEVICE;
this.timeout = config.getTimeout();
this.isConcurrent = config.getIsConcurrent();
this.isShare = config.getIsShare();
@ -184,10 +189,10 @@ public class SaLoginParameter {
* @return 获取device参数如果为null则返回默认值
*/
public String getDeviceOrDefault() {
if(device == null) {
if(deviceType == null) {
return SaTokenConsts.DEFAULT_LOGIN_DEVICE;
}
return device;
return deviceType;
}
/**
@ -207,16 +212,35 @@ public class SaLoginParameter {
/**
* @return 此次登录的客户端设备类型
*/
public String getDevice() {
return device;
public String getDeviceType() {
return deviceType;
}
/**
* @param device 此次登录的客户端设备类型
* @param deviceType 此次登录的客户端设备类型
* @return 对象自身
*/
public SaLoginParameter setDevice(String device) {
this.device = device;
public SaLoginParameter setDeviceType(String deviceType) {
this.deviceType = deviceType;
return this;
}
/**
* 获取 此次登录的客户端设备id
*
* @return deviceId 此次登录的客户端设备id
*/
public String getDeviceId() {
return this.deviceId;
}
/**
* 设置 此次登录的客户端设备id
*
* @param deviceId 此次登录的客户端设备id
*/
public SaLoginParameter setDeviceId(String deviceId) {
this.deviceId = deviceId;
return this;
}
@ -381,22 +405,22 @@ public class SaLoginParameter {
}
/**
* 获取 本次登录挂载到 TokenSign 数据
* 获取 本次登录挂载到 SaTerminalInfo 的自定义数据
*
* @return tokenSignTag 本次登录挂载到 TokenSign 数据
* @return 本次登录挂载到 SaTerminalInfo 的自定义数据
*/
public Object getTokenSignTag() {
return this.tokenSignTag;
public Object getTerminalTag() {
return this.terminalTag;
}
/**
* 设置 本次登录挂载到 TokenSign 数据
* 设置 本次登录挂载到 SaTerminalInfo 的自定义数据
*
* @param tokenSignTag 本次登录挂载到 TokenSign 数据
* @param terminalTag 本次登录挂载到 SaTerminalInfo 的自定义数据
* @return 对象自身
*/
public SaLoginParameter setTokenSignTag(Object tokenSignTag) {
this.tokenSignTag = tokenSignTag;
public SaLoginParameter setTerminalTag(Object terminalTag) {
this.terminalTag = terminalTag;
return this;
}
@ -406,7 +430,8 @@ public class SaLoginParameter {
@Override
public String toString() {
return "SaLoginParameter ["
+ "device=" + device
+ "deviceType=" + deviceType
+ ", deviceId=" + deviceId
+ ", isLastingCookie=" + isLastingCookie
+ ", timeout=" + timeout
+ ", activeTimeout=" + activeTimeout
@ -417,10 +442,31 @@ public class SaLoginParameter {
+ ", extraData=" + extraData
+ ", token=" + token
+ ", isWriteHeader=" + isWriteHeader
+ ", tokenSignTag=" + tokenSignTag
+ ", terminalTag=" + terminalTag
+ "]";
}
/**
* <h2> 请更换为 getDeviceType </h2>
* @return 此次登录的客户端设备类型
*/
@Deprecated
public String getDevice() {
return deviceType;
}
/**
* <h2> 请更换为 setDeviceType </h2>
* @param device 此次登录的客户端设备类型
* @return 对象自身
*/
@Deprecated
public SaLoginParameter setDevice(String device) {
this.deviceType = device;
return this;
}
}

View File

@ -69,7 +69,7 @@ public class SaTokenInfo {
public long tokenActiveTimeout;
/** 登录设备类型 */
public String loginDevice;
public String loginDeviceType;
/** 自定义数据(暂无意义,留作扩展) */
public String tag;
@ -205,15 +205,15 @@ public class SaTokenInfo {
/**
* @return 登录设备类型
*/
public String getLoginDevice() {
return loginDevice;
public String getLoginDeviceType() {
return loginDeviceType;
}
/**
* @param loginDevice 登录设备类型
* @param loginDeviceType 登录设备类型
*/
public void setLoginDevice(String loginDevice) {
this.loginDevice = loginDevice;
public void setLoginDeviceType(String loginDeviceType) {
this.loginDeviceType = loginDeviceType;
}
/**
@ -238,7 +238,7 @@ public class SaTokenInfo {
return "SaTokenInfo [tokenName=" + tokenName + ", tokenValue=" + tokenValue + ", isLogin=" + isLogin
+ ", loginId=" + loginId + ", loginType=" + loginType + ", tokenTimeout=" + tokenTimeout
+ ", sessionTimeout=" + sessionTimeout + ", tokenSessionTimeout=" + tokenSessionTimeout
+ ", tokenActiveTimeout=" + tokenActiveTimeout + ", loginDevice=" + loginDevice + ", tag=" + tag
+ ", tokenActiveTimeout=" + tokenActiveTimeout + ", loginDeviceType=" + loginDeviceType + ", tag=" + tag
+ "]";
}

View File

@ -16,7 +16,6 @@
package cn.dev33.satoken.stp;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.annotation.*;
import cn.dev33.satoken.config.SaCookieConfig;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.context.SaHolder;
@ -25,13 +24,13 @@ import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.context.model.SaResponse;
import cn.dev33.satoken.context.model.SaStorage;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.session.SaTerminalInfo;
import cn.dev33.satoken.error.SaErrorCode;
import cn.dev33.satoken.exception.*;
import cn.dev33.satoken.fun.SaFunction;
import cn.dev33.satoken.listener.SaTokenEventCenter;
import cn.dev33.satoken.model.wrapperInfo.SaDisableWrapperInfo;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.session.TokenSign;
import cn.dev33.satoken.strategy.SaStrategy;
import cn.dev33.satoken.util.SaFoxUtil;
import cn.dev33.satoken.util.SaTokenConsts;
@ -154,12 +153,12 @@ public class StpLogic {
* 为指定账号创建一个 token 只是把 token 创建出来并不持久化存储
*
* @param loginId 账号id
* @param device 设备类型
* @param deviceType 设备类型
* @param timeout 过期时间
* @param extraData 扩展信息
* @return 生成的tokenValue
*/
public String createTokenValue(Object loginId, String device, long timeout, Map<String, Object> extraData) {
public String createTokenValue(Object loginId, String deviceType, long timeout, Map<String, Object> extraData) {
return SaStrategy.instance.createToken.apply(loginId, loginType);
}
@ -381,7 +380,7 @@ public class StpLogic {
info.sessionTimeout = getSessionTimeout();
info.tokenSessionTimeout = getTokenSessionTimeout();
info.tokenActiveTimeout = getTokenActiveTimeout();
info.loginDevice = getLoginDevice();
info.loginDeviceType = getLoginDeviceType();
return info;
}
@ -403,10 +402,10 @@ public class StpLogic {
* 会话登录并指定登录设备类型
*
* @param id 账号id建议的类型long | int | String
* @param device 设备类型
* @param deviceType 设备类型
*/
public void login(Object id, String device) {
login(id, createSaLoginParameter().setDevice(device));
public void login(Object id, String deviceType) {
login(id, createSaLoginParameter().setDeviceType(deviceType));
}
/**
@ -462,8 +461,6 @@ public class StpLogic {
*/
public String createLoginSession(Object id, SaLoginParameter loginParameter) {
SaTokenConfig config = getConfigOrGlobal();
// 1先检查一下传入的参数是否有效
checkLoginArgs(id, loginParameter);
@ -474,9 +471,15 @@ public class StpLogic {
SaSession session = getSessionByLoginId(id, true, loginParameter.getTimeout());
session.updateMinTimeout(loginParameter.getTimeout());
// 4 Account-Session 上记录本次登录的 token 签名
TokenSign tokenSign = new TokenSign(tokenValue, loginParameter.getDevice(), loginParameter.getTokenSignTag());
session.addTokenSign(tokenSign);
// 4 Account-Session 上记录本次登录的终端信息
SaTerminalInfo terminalInfo = new SaTerminalInfo()
.setIndex(session.maxTerminalIndex() + 1)
.setDeviceType(loginParameter.getDeviceType())
.setDeviceId(loginParameter.getDeviceId())
.setTokenValue(tokenValue)
.setTag(loginParameter.getTerminalTag())
.setCreateTime(System.currentTimeMillis());
session.addTerminal(terminalInfo);
// 5保存 token -> id 的映射关系方便日后根据 token 找账号 id
saveTokenToIdMapping(tokenValue, id, loginParameter.getTimeout());
@ -517,7 +520,7 @@ public class StpLogic {
// 如果配置为不允许一个账号多地同时登录则需要先将这个账号的历史登录会话标记为被顶下线
if( ! loginParameter.getIsConcurrent()) {
// TODO 此处应该加一个配置决定是只顶掉当前设备类型还是所有类型
replaced(id, loginParameter.getDevice());
replaced(id, loginParameter.getDeviceType());
}
// 2如果调用者预定了要生成的 token则直接返回这个预定的值框架无需再操心了
@ -532,7 +535,7 @@ public class StpLogic {
if(isSupportShareToken() && loginParameter.getIsShare()) {
// 根据 账号id + 设备类型尝试获取旧的 token
String tokenValue = getTokenValueByLoginId(id, loginParameter.getDevice());
String tokenValue = getTokenValueByLoginId(id, loginParameter.getDeviceType());
// 如果有值那就直接复用
if(SaFoxUtil.isNotEmpty(tokenValue)) {
@ -549,7 +552,7 @@ public class StpLogic {
"token",
getConfigOfMaxTryTimes(loginParameter),
() -> {
return createTokenValue(id, loginParameter.getDevice(), loginParameter.getTimeout(), loginParameter.getExtraData());
return createTokenValue(id, loginParameter.getDeviceType(), loginParameter.getTimeout(), loginParameter.getExtraData());
},
tokenValue -> {
return getLoginIdNotHandle(tokenValue) == null;
@ -662,21 +665,21 @@ public class StpLogic {
* 会话注销根据账号id 设备类型
*
* @param loginId 账号id
* @param device 设备类型 ( null 代表注销该账号的所有设备类型)
* @param deviceType 设备类型 ( null 代表注销该账号的所有设备类型)
*/
public void logout(Object loginId, String device) {
public void logout(Object loginId, String deviceType) {
// 1获取此账号的 Account-Session上面记录了此账号的所有登录客户端数据
SaSession session = getSessionByLoginId(loginId, false);
if(session != null) {
// 2遍历此账号所有从这个 device 设备上登录的客户端清除相关数据
for (TokenSign tokenSign: session.getTokenSignListByDevice(device)) {
// 2遍历此账号所有从这个 deviceType 设备类型上登录的客户端清除相关数据
for (SaTerminalInfo terminal: session.getTerminalListByDeviceType(deviceType)) {
// 2.1获取此客户端的 token
String tokenValue = tokenSign.getValue();
String tokenValue = terminal.getTokenValue();
// 2.2 Account-Session 上清除 token 签名
session.removeTokenSign(tokenValue);
// 2.2 Account-Session 上清除此设备信息
session.removeTerminal(tokenValue);
// 2.3清除这个 token 的最后活跃时间记录
if(isOpenCheckActiveTimeout()) {
@ -694,7 +697,7 @@ public class StpLogic {
}
// 3如果代码走到这里的时候此账号已经没有客户端在登录了则直接注销掉这个 Account-Session
session.logoutByTokenSignCountToZero();
session.logoutByTerminalCountToZero();
}
}
@ -703,10 +706,10 @@ public class StpLogic {
*
* @param loginId 账号id
* @param session 此账号的 Account-Session 对象可填写 null框架将自动获取
* @param device 设备类型 null 代表注销此账号所有设备类型的登录
* @param deviceType 设备类型 null 代表注销此账号所有设备类型的登录
* @param maxLoginCount 最大登录数量超过此数量的将被注销
*/
public void logoutByMaxLoginCount(Object loginId, SaSession session, String device, int maxLoginCount) {
public void logoutByMaxLoginCount(Object loginId, SaSession session, String deviceType, int maxLoginCount) {
// 1如果调用者提供的 Account-Session 对象为空则我们先手动获取一下
if(session == null) {
@ -717,16 +720,16 @@ public class StpLogic {
}
// 2获取这个账号指定设备类型下的所有登录客户端
List<TokenSign> list = session.getTokenSignListByDevice(device);
List<SaTerminalInfo> list = session.getTerminalListByDeviceType(deviceType);
// 3按照登录时间倒叙超过 maxLoginCount 数量的全部注销掉
for (int i = 0; i < list.size() - maxLoginCount; i++) {
// 3.1获取此客户端的 token
String tokenValue = list.get(i).getValue();
String tokenValue = list.get(i).getTokenValue();
// 3.2 Account-Session 上清除 token 签名
session.removeTokenSign(tokenValue);
// 3.2 Account-Session 上清除 terminal 信息
session.removeTerminal(tokenValue);
// 3.3清除这个 token 的最后活跃时间记录
if(isOpenCheckActiveTimeout()) {
@ -744,7 +747,7 @@ public class StpLogic {
}
// 4如果代码走到这里的时候此账号已经没有客户端在登录了则直接注销掉这个 Account-Session
session.logoutByTokenSignCountToZero();
session.logoutByTerminalCountToZero();
}
/**
@ -775,11 +778,11 @@ public class StpLogic {
// 5$$ 发布事件某某账号的某某 token 注销下线了
SaTokenEventCenter.doLogout(loginType, loginId, tokenValue);
// 6清理这个账号的 Account-Session 上的 token 签名并且尝试注销掉 Account-Session
// 6清理这个账号的 Account-Session 上的 terminal 信息并且尝试注销掉 Account-Session
SaSession session = getSessionByLoginId(loginId, false);
if(session != null) {
session.removeTokenSign(tokenValue);
session.logoutByTokenSignCountToZero();
session.removeTerminal(tokenValue);
session.logoutByTerminalCountToZero();
}
}
@ -798,21 +801,21 @@ public class StpLogic {
* <p> 当对方再次访问系统时会抛出 NotLoginException 异常场景值=-5 </p>
*
* @param loginId 账号id
* @param device 设备类型 ( null 代表踢出该账号的所有设备类型)
* @param deviceType 设备类型 ( null 代表踢出该账号的所有设备类型)
*/
public void kickout(Object loginId, String device) {
public void kickout(Object loginId, String deviceType) {
// 1获取此账号的 Account-Session上面记录了此账号的所有登录客户端数据
SaSession session = getSessionByLoginId(loginId, false);
if(session != null) {
// 2遍历此账号所有从这个 device 设备上登录的客户端清除相关数据
for (TokenSign tokenSign: session.getTokenSignListByDevice(device)) {
// 2遍历此账号所有从这个 deviceType 设备上登录的客户端清除相关数据
for (SaTerminalInfo terminal: session.getTerminalListByDeviceType(deviceType)) {
// 2.1获取此客户端的 token
String tokenValue = tokenSign.getValue();
String tokenValue = terminal.getTokenValue();
// 2.2 Account-Session 上清除 token 签名
session.removeTokenSign(tokenValue);
// 2.2 Account-Session 上清除 terminal 信息
session.removeTerminal(tokenValue);
// 2.3清除这个 token 的最后活跃时间记录
if(isOpenCheckActiveTimeout()) {
@ -830,7 +833,7 @@ public class StpLogic {
}
// 3如果代码走到这里的时候此账号已经没有客户端在登录了则直接注销掉这个 Account-Session
session.logoutByTokenSignCountToZero();
session.logoutByTerminalCountToZero();
}
}
@ -861,11 +864,11 @@ public class StpLogic {
// 5$$. 发布事件某某 token 被踢下线了
SaTokenEventCenter.doKickout(loginType, loginId, tokenValue);
// 6清理这个账号的 Account-Session 上的 token 签名并且尝试注销掉 Account-Session
// 6清理这个账号的 Account-Session 上的 terminal 信息并且尝试注销掉 Account-Session
SaSession session = getSessionByLoginId(loginId, false);
if(session != null) {
session.removeTokenSign(tokenValue);
session.logoutByTokenSignCountToZero();
session.removeTerminal(tokenValue);
session.logoutByTerminalCountToZero();
}
}
@ -874,21 +877,21 @@ public class StpLogic {
* <p> 当对方再次访问系统时会抛出 NotLoginException 异常场景值=-4 </p>
*
* @param loginId 账号id
* @param device 设备类型 null 代表顶替该账号的所有设备类型
* @param deviceType 设备类型 null 代表顶替该账号的所有设备类型
*/
public void replaced(Object loginId, String device) {
public void replaced(Object loginId, String deviceType) {
// 1获取此账号的 Account-Session上面记录了此账号的所有登录客户端数据
SaSession session = getSessionByLoginId(loginId, false);
if(session != null) {
// 2遍历此账号所有从这个 device 设备上登录的客户端清除相关数据
for (TokenSign tokenSign: session.getTokenSignListByDevice(device)) {
// 2遍历此账号所有从这个 deviceType 设备上登录的客户端清除相关数据
for (SaTerminalInfo ter: session.getTerminalListByDeviceType(deviceType)) {
// 2.1获取此客户端的 token
String tokenValue = tokenSign.getValue();
String tokenValue = ter.getTokenValue();
// 2.2 Account-Session 上清除 token 签名
session.removeTokenSign(tokenValue);
// 2.2 Account-Session 上清除 terminal 信息
session.removeTerminal(tokenValue);
// 2.3清除这个 token 的最后活跃时间记录
if(isOpenCheckActiveTimeout()) {
@ -906,7 +909,7 @@ public class StpLogic {
}
// 3因为调用顶替下线时一般都是在新客户端正在登录所以此处不需要清除该账号的 Account-Session
// session.logoutByTokenSignCountToZero();
// session.logoutByTerminalCountToZero();
}
}
@ -930,8 +933,8 @@ public class StpLogic {
* @return 已登录返回 true未登录返回 false
*/
public boolean isLogin(Object loginId) {
// 判断条件能否根据 loginId 查询到对应的 tokenSign
return getTokenSignListByLoginId(loginId, null).size() > 0;
// 判断条件能否根据 loginId 查询到对应的 terminal
return !getTerminalListByLoginId(loginId, null).isEmpty();
}
/**
@ -2103,11 +2106,11 @@ public class StpLogic {
* </p>
*
* @param loginId 账号id
* @param device 设备类型 null 代表不限设备类型
* @param deviceType 设备类型 null 代表不限设备类型
* @return token值
*/
public String getTokenValueByLoginId(Object loginId, String device) {
List<String> tokenValueList = getTokenValueListByLoginId(loginId, device);
public String getTokenValueByLoginId(Object loginId, String deviceType) {
List<String> tokenValueList = getTokenValueListByLoginId(loginId, deviceType);
return tokenValueList.isEmpty() ? null : tokenValueList.get(tokenValueList.size() - 1);
}
@ -2125,10 +2128,10 @@ public class StpLogic {
* 获取指定账号 id 指定设备类型端的 token 集合
*
* @param loginId 账号id
* @param device 设备类型 null 代表不限设备类型
* @param deviceType 设备类型 null 代表不限设备类型
* @return loginId 的所有登录 token
*/
public List<String> getTokenValueListByLoginId(Object loginId, String device) {
public List<String> getTokenValueListByLoginId(Object loginId, String deviceType) {
// 如果该账号的 Account-Session null说明此账号尚没有客户端在登录此时返回空集合
SaSession session = getSessionByLoginId(loginId, false);
if(session == null) {
@ -2136,17 +2139,17 @@ public class StpLogic {
}
// 按照设备类型进行筛选
return session.getTokenValueListByDevice(device);
return session.getTokenValueListByDeviceType(deviceType);
}
/**
* 获取指定账号 id 指定设备类型端的 tokenSign 集合
* 获取指定账号 id 指定设备类型端的 Terminal 集合
*
* @param loginId 账号id
* @param device 设备类型 null 代表不限设备类型
* @param deviceType 设备类型 null 代表不限设备类型
* @return loginId 的所有登录 token
*/
public List<TokenSign> getTokenSignListByLoginId(Object loginId, String device) {
public List<SaTerminalInfo> getTerminalListByLoginId(Object loginId, String deviceType) {
// 如果该账号的 Account-Session null说明此账号尚没有客户端在登录此时返回空集合
SaSession session = getSessionByLoginId(loginId, false);
if(session == null) {
@ -2154,7 +2157,7 @@ public class StpLogic {
}
// 按照设备类型进行筛选
return session.getTokenSignListByDevice(device);
return session.getTerminalListByDeviceType(deviceType);
}
/**
@ -2162,8 +2165,8 @@ public class StpLogic {
*
* @return 当前令牌的登录设备类型
*/
public String getLoginDevice() {
return getLoginDeviceByToken(getTokenValue());
public String getLoginDeviceType() {
return getLoginDeviceTypeByToken(getTokenValue());
}
/**
@ -2172,7 +2175,7 @@ public class StpLogic {
* @param tokenValue 指定token
* @return 当前令牌的登录设备类型
*/
public String getLoginDeviceByToken(String tokenValue) {
public String getLoginDeviceTypeByToken(String tokenValue) {
// 1如果 token null直接提前返回
if(SaFoxUtil.isEmpty(tokenValue)) {
return null;
@ -2196,10 +2199,10 @@ public class StpLogic {
}
// 5遍历 Account-Session 上的客户端 token 列表寻找当前 token 对应的设备类型
List<TokenSign> tokenSignList = session.tokenSignListCopy();
for (TokenSign tokenSign : tokenSignList) {
if(tokenSign.getValue().equals(tokenValue)) {
return tokenSign.getDevice();
List<SaTerminalInfo> terminalList = session.terminalListCopy();
for (SaTerminalInfo terminal : terminalList) {
if(terminal.getTokenValue().equals(tokenValue)) {
return terminal.getDeviceType();
}
}
@ -2904,79 +2907,26 @@ public class StpLogic {
// ------------------- 过期方法 -------------------
/**
* 根据注解 ( @SaCheckLogin ) 鉴权
* <h2>请更换为 getLoginDeviceType </h2>
* 返回当前会话的登录设备类型
*
* @param at 注解对象
* @return 当前令牌的登录设备类型
*/
@Deprecated
public void checkByAnnotation(SaCheckLogin at) {
this.checkLogin();
public String getLoginDevice() {
return getLoginDeviceType();
}
/**
* 根据注解 ( @SaCheckRole ) 鉴权
* <h2>请更换为 getLoginDeviceTypeByToken </h2>
* 返回指定 token 会话的登录设备类型
*
* @param at 注解对象
* @param tokenValue 指定token
* @return 当前令牌的登录设备类型
*/
@Deprecated
public void checkByAnnotation(SaCheckRole at) {
String[] roleArray = at.value();
if(at.mode() == SaMode.AND) {
this.checkRoleAnd(roleArray);
} else {
this.checkRoleOr(roleArray);
}
public String getLoginDeviceByToken(String tokenValue) {
return getLoginDeviceTypeByToken(tokenValue);
}
/**
* 根据注解 ( @SaCheckPermission ) 鉴权
*
* @param at 注解对象
*/
@Deprecated
public void checkByAnnotation(SaCheckPermission at) {
String[] permissionArray = at.value();
try {
if(at.mode() == SaMode.AND) {
this.checkPermissionAnd(permissionArray);
} else {
this.checkPermissionOr(permissionArray);
}
} catch (NotPermissionException e) {
// 权限认证校验未通过再开始角色认证校验
for (String role : at.orRole()) {
String[] rArr = SaFoxUtil.convertStringToArray(role);
// 某一项 role 认证通过则可以提前退出了代表通过
if (hasRoleAnd(rArr)) {
return;
}
}
throw e;
}
}
/**
* 根据注解 ( @SaCheckSafe ) 鉴权
*
* @param at 注解对象
*/
@Deprecated
public void checkByAnnotation(SaCheckSafe at) {
this.checkSafe(at.value());
}
/**
* 根据注解 ( @SaCheckDisable ) 鉴权
*
* @param at 注解对象
*/
@Deprecated
public void checkByAnnotation(SaCheckDisable at) {
Object loginId = getLoginId();
for (String service : at.value()) {
this.checkDisableLevel(loginId, service, at.level());
}
}
}

View File

@ -16,10 +16,10 @@
package cn.dev33.satoken.stp;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.session.SaTerminalInfo;
import cn.dev33.satoken.fun.SaFunction;
import cn.dev33.satoken.listener.SaTokenEventCenter;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.session.TokenSign;
import java.util.List;
@ -168,10 +168,10 @@ public class StpUtil {
* 会话登录并指定登录设备类型
*
* @param id 账号id建议的类型long | int | String
* @param device 设备类型
* @param deviceType 设备类型
*/
public static void login(Object id, String device) {
stpLogic.login(id, device);
public static void login(Object id, String deviceType) {
stpLogic.login(id, deviceType);
}
/**
@ -257,10 +257,10 @@ public class StpUtil {
* 会话注销根据账号id 设备类型
*
* @param loginId 账号id
* @param device 设备类型 ( null 代表注销该账号的所有设备类型)
* @param deviceType 设备类型 ( null 代表注销该账号的所有设备类型)
*/
public static void logout(Object loginId, String device) {
stpLogic.logout(loginId, device);
public static void logout(Object loginId, String deviceType) {
stpLogic.logout(loginId, deviceType);
}
/**
@ -287,10 +287,10 @@ public class StpUtil {
* <p> 当对方再次访问系统时会抛出 NotLoginException 异常场景值=-5 </p>
*
* @param loginId 账号id
* @param device 设备类型 ( null 代表踢出该账号的所有设备类型)
* @param deviceType 设备类型 ( null 代表踢出该账号的所有设备类型)
*/
public static void kickout(Object loginId, String device) {
stpLogic.kickout(loginId, device);
public static void kickout(Object loginId, String deviceType) {
stpLogic.kickout(loginId, deviceType);
}
/**
@ -308,10 +308,10 @@ public class StpUtil {
* <p> 当对方再次访问系统时会抛出 NotLoginException 异常场景值=-4 </p>
*
* @param loginId 账号id
* @param device 设备类型 null 代表顶替该账号的所有设备类型
* @param deviceType 设备类型 null 代表顶替该账号的所有设备类型
*/
public static void replaced(Object loginId, String device) {
stpLogic.replaced(loginId, device);
public static void replaced(Object loginId, String deviceType) {
stpLogic.replaced(loginId, deviceType);
}
// 会话查询
@ -806,11 +806,11 @@ public class StpUtil {
* </p>
*
* @param loginId 账号id
* @param device 设备类型 null 代表不限设备类型
* @param deviceType 设备类型 null 代表不限设备类型
* @return token值
*/
public static String getTokenValueByLoginId(Object loginId, String device) {
return stpLogic.getTokenValueByLoginId(loginId, device);
public static String getTokenValueByLoginId(Object loginId, String deviceType) {
return stpLogic.getTokenValueByLoginId(loginId, deviceType);
}
/**
@ -827,22 +827,22 @@ public class StpUtil {
* 获取指定账号 id 指定设备类型端的 token 集合
*
* @param loginId 账号id
* @param device 设备类型 null 代表不限设备类型
* @param deviceType 设备类型 null 代表不限设备类型
* @return loginId 的所有登录 token
*/
public static List<String> getTokenValueListByLoginId(Object loginId, String device) {
return stpLogic.getTokenValueListByLoginId(loginId, device);
public static List<String> getTokenValueListByLoginId(Object loginId, String deviceType) {
return stpLogic.getTokenValueListByLoginId(loginId, deviceType);
}
/**
* 获取指定账号 id 指定设备类型端的 tokenSign 集合
* 获取指定账号 id 指定设备类型端的 SaTerminalInfo 集合
*
* @param loginId 账号id
* @param device 设备类型 null 代表不限设备类型
* @return loginId 的所有登录 tokenSign
* @param deviceType 设备类型 null 代表不限设备类型
* @return /
*/
public static List<TokenSign> getTokenSignListByLoginId(Object loginId, String device) {
return stpLogic.getTokenSignListByLoginId(loginId, device);
public static List<SaTerminalInfo> getTerminalListByLoginId(Object loginId, String deviceType) {
return stpLogic.getTerminalListByLoginId(loginId, deviceType);
}
/**
@ -850,8 +850,8 @@ public class StpUtil {
*
* @return 当前令牌的登录设备类型
*/
public static String getLoginDevice() {
return stpLogic.getLoginDevice();
public static String getLoginDeviceType() {
return stpLogic.getLoginDeviceType();
}
/**
@ -860,8 +860,8 @@ public class StpUtil {
* @param tokenValue 指定token
* @return 当前令牌的登录设备类型
*/
public static String getLoginDeviceByToken(String tokenValue) {
return stpLogic.getLoginDeviceByToken(tokenValue);
public static String getLoginDeviceTypeByToken(String tokenValue) {
return stpLogic.getLoginDeviceTypeByToken(tokenValue);
}
/**
@ -1272,4 +1272,30 @@ public class StpUtil {
return stpLogic.createSaLoginParameter();
}
// ------------------- 过期方法 -------------------
/**
* <h2>请更换为 getLoginDeviceType </h2>
* 返回当前会话的登录设备类型
*
* @return 当前令牌的登录设备类型
*/
@Deprecated
public static String getLoginDevice() {
return stpLogic.getLoginDevice();
}
/**
* <h2>请更换为 getLoginDeviceTypeByToken </h2>
* 返回指定 token 会话的登录设备类型
*
* @param tokenValue 指定token
* @return 当前令牌的登录设备类型
*/
@Deprecated
public static String getLoginDeviceByToken(String tokenValue) {
return stpLogic.getLoginDeviceByToken(tokenValue);
}
}

View File

@ -109,7 +109,7 @@ public class LoginAuthController {
System.out.println("当前是否登录:" + info.getIsLogin());
System.out.println("当前登录的账号id" + info.getLoginId());
System.out.println("当前登录账号的类型:" + info.getLoginType());
System.out.println("当前登录客户端的设备类型:" + info.getLoginDevice());
System.out.println("当前登录客户端的设备类型:" + info.getLoginDeviceType());
System.out.println("当前 Token 的剩余有效期:" + info.getTokenTimeout()); // 单位-1代表永久有效-2代表值不存在
System.out.println("当前 Token 距离被冻结还剩:" + info.getTokenActiveTimeout()); // 单位-1代表永久有效-2代表值不存在
System.out.println("当前 Account-Session 的剩余有效期" + info.getSessionTimeout()); // 单位-1代表永久有效-2代表值不存在

View File

@ -4,21 +4,19 @@ import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.fun.SaFunction;
import cn.dev33.satoken.listener.SaTokenEventCenter;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.session.TokenSign;
import cn.dev33.satoken.session.SaTerminalInfo;
import cn.dev33.satoken.stp.SaLoginParameter;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpLogic;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* Sa-Token 权限认证工具类User版
* Sa-Token 权限认证工具类 (User )
*
* @author click33
* @since 1.0.0
*/
@Component
public class StpUserUtil {
private StpUserUtil() {}
@ -158,10 +156,10 @@ public class StpUserUtil {
* 会话登录并指定登录设备类型
*
* @param id 账号id建议的类型long | int | String
* @param device 设备类型
* @param deviceType 设备类型
*/
public static void login(Object id, String device) {
stpLogic.login(id, device);
public static void login(Object id, String deviceType) {
stpLogic.login(id, deviceType);
}
/**
@ -247,10 +245,10 @@ public class StpUserUtil {
* 会话注销根据账号id 设备类型
*
* @param loginId 账号id
* @param device 设备类型 ( null 代表注销该账号的所有设备类型)
* @param deviceType 设备类型 ( null 代表注销该账号的所有设备类型)
*/
public static void logout(Object loginId, String device) {
stpLogic.logout(loginId, device);
public static void logout(Object loginId, String deviceType) {
stpLogic.logout(loginId, deviceType);
}
/**
@ -277,10 +275,10 @@ public class StpUserUtil {
* <p> 当对方再次访问系统时会抛出 NotLoginException 异常场景值=-5 </p>
*
* @param loginId 账号id
* @param device 设备类型 ( null 代表踢出该账号的所有设备类型)
* @param deviceType 设备类型 ( null 代表踢出该账号的所有设备类型)
*/
public static void kickout(Object loginId, String device) {
stpLogic.kickout(loginId, device);
public static void kickout(Object loginId, String deviceType) {
stpLogic.kickout(loginId, deviceType);
}
/**
@ -298,10 +296,10 @@ public class StpUserUtil {
* <p> 当对方再次访问系统时会抛出 NotLoginException 异常场景值=-4 </p>
*
* @param loginId 账号id
* @param device 设备类型 null 代表顶替该账号的所有设备类型
* @param deviceType 设备类型 null 代表顶替该账号的所有设备类型
*/
public static void replaced(Object loginId, String device) {
stpLogic.replaced(loginId, device);
public static void replaced(Object loginId, String deviceType) {
stpLogic.replaced(loginId, deviceType);
}
// 会话查询
@ -796,11 +794,11 @@ public class StpUserUtil {
* </p>
*
* @param loginId 账号id
* @param device 设备类型 null 代表不限设备类型
* @param deviceType 设备类型 null 代表不限设备类型
* @return token值
*/
public static String getTokenValueByLoginId(Object loginId, String device) {
return stpLogic.getTokenValueByLoginId(loginId, device);
public static String getTokenValueByLoginId(Object loginId, String deviceType) {
return stpLogic.getTokenValueByLoginId(loginId, deviceType);
}
/**
@ -817,22 +815,22 @@ public class StpUserUtil {
* 获取指定账号 id 指定设备类型端的 token 集合
*
* @param loginId 账号id
* @param device 设备类型 null 代表不限设备类型
* @param deviceType 设备类型 null 代表不限设备类型
* @return loginId 的所有登录 token
*/
public static List<String> getTokenValueListByLoginId(Object loginId, String device) {
return stpLogic.getTokenValueListByLoginId(loginId, device);
public static List<String> getTokenValueListByLoginId(Object loginId, String deviceType) {
return stpLogic.getTokenValueListByLoginId(loginId, deviceType);
}
/**
* 获取指定账号 id 指定设备类型端的 tokenSign 集合
* 获取指定账号 id 指定设备类型端的 SaTerminalInfo 集合
*
* @param loginId 账号id
* @param device 设备类型 null 代表不限设备类型
* @return loginId 的所有登录 tokenSign
* @param deviceType 设备类型 null 代表不限设备类型
* @return /
*/
public static List<TokenSign> getTokenSignListByLoginId(Object loginId, String device) {
return stpLogic.getTokenSignListByLoginId(loginId, device);
public static List<SaTerminalInfo> getTerminalListByLoginId(Object loginId, String deviceType) {
return stpLogic.getTerminalListByLoginId(loginId, deviceType);
}
/**
@ -840,8 +838,8 @@ public class StpUserUtil {
*
* @return 当前令牌的登录设备类型
*/
public static String getLoginDevice() {
return stpLogic.getLoginDevice();
public static String getLoginDeviceType() {
return stpLogic.getLoginDeviceType();
}
/**
@ -850,8 +848,8 @@ public class StpUserUtil {
* @param tokenValue 指定token
* @return 当前令牌的登录设备类型
*/
public static String getLoginDeviceByToken(String tokenValue) {
return stpLogic.getLoginDeviceByToken(tokenValue);
public static String getLoginDeviceTypeByToken(String tokenValue) {
return stpLogic.getLoginDeviceTypeByToken(tokenValue);
}
/**
@ -1250,4 +1248,42 @@ public class StpUserUtil {
stpLogic.closeSafe(service);
}
// ------------------- Bean 对象字段代理 -------------------
/**
* 根据当前配置对象创建一个 SaLoginParameter 对象
*
* @return /
*/
public static SaLoginParameter createSaLoginParameter() {
return stpLogic.createSaLoginParameter();
}
// ------------------- 过期方法 -------------------
/**
* <h2>请更换为 getLoginDeviceType </h2>
* 返回当前会话的登录设备类型
*
* @return 当前令牌的登录设备类型
*/
@Deprecated
public static String getLoginDevice() {
return stpLogic.getLoginDevice();
}
/**
* <h2>请更换为 getLoginDeviceTypeByToken </h2>
* 返回指定 token 会话的登录设备类型
*
* @param tokenValue 指定token
* @return 当前令牌的登录设备类型
*/
@Deprecated
public static String getLoginDeviceByToken(String tokenValue) {
return stpLogic.getLoginDeviceByToken(tokenValue);
}
}

View File

@ -818,7 +818,7 @@ public class StpUserUtil {
* @return 当前令牌的登录设备类型
*/
public static String getLoginDevice() {
return stpLogic.getLoginDevice();
return stpLogic.getLoginDeviceType();
}

View File

@ -7,6 +7,6 @@
- https://www.jb51.net/program/297714rev.htm
- https://www.bilibili.com/video/BV1WZ421W7Qx
- https://blog.csdn.net/Tomwildboar/article/details/139199801
- 单元测试 - https://www.cnblogs.com/flypig666/p/11505277.html

View File

@ -50,7 +50,7 @@ public class SaJwtTemplate {
/**
* key登录设备类型
*/
public static final String DEVICE = "device";
public static final String DEVICE_TYPE = "deviceType";
/**
* key有效截止期 (时间戳)
@ -103,13 +103,13 @@ public class SaJwtTemplate {
*
* @param loginType 账号类型
* @param loginId 账号id
* @param device 设备类型
* @param deviceType 设备类型
* @param timeout token有效期 (单位 )
* @param extraData 扩展数据
* @param keyt 秘钥
* @return jwt-token
*/
public String createToken(String loginType, Object loginId, String device,
public String createToken(String loginType, Object loginId, String deviceType,
long timeout, Map<String, Object> extraData, String keyt) {
// 计算 eff 有效期
@ -124,7 +124,7 @@ public class SaJwtTemplate {
JWT jwt = JWT.create()
.setPayload(LOGIN_TYPE, loginType)
.setPayload(LOGIN_ID, loginId)
.setPayload(DEVICE, device)
.setPayload(DEVICE_TYPE, deviceType)
.setPayload(EFF, effTime)
// 塞入一个随机字符串防止同账号同一毫秒下每次生成的 token 都一样的
.setPayload(RN_STR, SaFoxUtil.getRandomString(32))

View File

@ -65,7 +65,7 @@ public class SaJwtUtil {
/**
* key登录设备类型
*/
public static final String DEVICE = SaJwtTemplate.DEVICE;
public static final String DEVICE_TYPE = SaJwtTemplate.DEVICE_TYPE;
/**
* key有效截止期 (时间戳)
@ -105,15 +105,15 @@ public class SaJwtUtil {
* 创建 jwt 全参数方式
* @param loginType 账号类型
* @param loginId 账号id
* @param device 设备类型
* @param deviceType 设备类型
* @param timeout token有效期 (单位 )
* @param extraData 扩展数据
* @param keyt 秘钥
* @return jwt-token
*/
public static String createToken(String loginType, Object loginId, String device,
public static String createToken(String loginType, Object loginId, String deviceType,
long timeout, Map<String, Object> extraData, String keyt) {
return saJwtTemplate.createToken(loginType, loginId, device, timeout, extraData, keyt);
return saJwtTemplate.createToken(loginType, loginId, deviceType, timeout, extraData, keyt);
}
/**

View File

@ -76,8 +76,8 @@ public class StpLogicJwtForMixin extends StpLogic {
* 创建一个TokenValue
*/
@Override
public String createTokenValue(Object loginId, String device, long timeout, Map<String, Object> extraData) {
return SaJwtUtil.createToken(loginType, loginId, device, timeout, extraData, jwtSecretKey());
public String createTokenValue(Object loginId, String deviceType, long timeout, Map<String, Object> extraData) {
return SaJwtUtil.createToken(loginType, loginId, deviceType, timeout, extraData, jwtSecretKey());
}
/**
@ -96,7 +96,7 @@ public class StpLogicJwtForMixin extends StpLogic {
info.sessionTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
info.tokenSessionTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
info.tokenActiveTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
info.loginDevice = getLoginDevice();
info.loginDeviceType = getLoginDeviceType();
return info;
}
@ -139,7 +139,7 @@ public class StpLogicJwtForMixin extends StpLogic {
* [禁用] 会话注销根据账号id 设备类型
*/
@Override
public void logout(Object loginId, String device) {
public void logout(Object loginId, String deviceType) {
throw new ApiDisabledException();
}
@ -155,7 +155,7 @@ public class StpLogicJwtForMixin extends StpLogic {
* [禁用] 踢人下线根据账号id 设备类型
*/
@Override
public void kickout(Object loginId, String device) {
public void kickout(Object loginId, String deviceType) {
throw new ApiDisabledException();
}
@ -171,7 +171,7 @@ public class StpLogicJwtForMixin extends StpLogic {
* [禁用] 顶人下线根据账号id 设备类型
*/
@Override
public void replaced(Object loginId, String device) {
public void replaced(Object loginId, String deviceType) {
throw new ApiDisabledException();
}

View File

@ -61,7 +61,7 @@ public class StpLogicJwtForSimple extends StpLogic {
* 创建一个TokenValue
*/
@Override
public String createTokenValue(Object loginId, String device, long timeout, Map<String, Object> extraData) {
public String createTokenValue(Object loginId, String deviceType, long timeout, Map<String, Object> extraData) {
return SaJwtUtil.createToken(loginType, loginId, extraData, jwtSecretKey());
}

View File

@ -73,8 +73,8 @@ public class StpLogicJwtForStateless extends StpLogic {
* 创建一个TokenValue
*/
@Override
public String createTokenValue(Object loginId, String device, long timeout, Map<String, Object> extraData) {
return SaJwtUtil.createToken(loginType, loginId, device, timeout, extraData, jwtSecretKey());
public String createTokenValue(Object loginId, String deviceType, long timeout, Map<String, Object> extraData) {
return SaJwtUtil.createToken(loginType, loginId, deviceType, timeout, extraData, jwtSecretKey());
}
/**
@ -93,7 +93,7 @@ public class StpLogicJwtForStateless extends StpLogic {
info.sessionTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
info.tokenSessionTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
info.tokenActiveTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
info.loginDevice = getLoginDevice();
info.loginDeviceType = getLoginDeviceType();
return info;
}
@ -112,7 +112,7 @@ public class StpLogicJwtForStateless extends StpLogic {
checkLoginArgs(id, loginParameter);
// 3生成一个token
String tokenValue = createTokenValue(id, loginParameter.getDevice(), loginParameter.getTimeout(), loginParameter.getExtraData());
String tokenValue = createTokenValue(id, loginParameter.getDeviceType(), loginParameter.getTimeout(), loginParameter.getExtraData());
// 4$$ 发布事件账号xxx 登录成功
SaTokenEventCenter.doLogin(loginType, id, tokenValue, loginParameter);
@ -193,7 +193,7 @@ public class StpLogicJwtForStateless extends StpLogic {
* @return 当前令牌的登录设备类型
*/
@Override
public String getLoginDevice() {
public String getLoginDeviceType() {
// 如果没有token直接返回 null
String tokenValue = getTokenValue();
if(tokenValue == null) {
@ -204,7 +204,7 @@ public class StpLogicJwtForStateless extends StpLogic {
return null;
}
// 获取
return SaJwtUtil.getPayloadsNotCheck(tokenValue, loginType, jwtSecretKey()).getStr(SaJwtUtil.DEVICE);
return SaJwtUtil.getPayloadsNotCheck(tokenValue, loginType, jwtSecretKey()).getStr(SaJwtUtil.DEVICE_TYPE);
}

View File

@ -65,7 +65,7 @@ public class JwtForMixinTest {
JWT jwt = JWT.of(token);
JSONObject payloads = jwt.getPayloads();
Assertions.assertEquals(payloads.getStr(SaJwtUtil.LOGIN_ID), "10001"); // 账号
Assertions.assertEquals(payloads.getStr(SaJwtUtil.DEVICE), SaTokenConsts.DEFAULT_LOGIN_DEVICE); // 登录设备类型
Assertions.assertEquals(payloads.getStr(SaJwtUtil.DEVICE_TYPE), SaTokenConsts.DEFAULT_LOGIN_DEVICE); // 登录设备类型
Assertions.assertEquals(payloads.getStr(SaJwtUtil.LOGIN_TYPE), StpUtil.TYPE); // 账号类型
// db数据 验证
@ -75,7 +75,7 @@ public class JwtForMixinTest {
SaSession session = dao.getSession("satoken:login:session:" + 10001);
Assertions.assertNotNull(session);
Assertions.assertEquals(session.getId(), "satoken:login:session:" + 10001);
Assertions.assertTrue(session.getTokenSignList().size() >= 1);
Assertions.assertTrue(session.getTerminalList().size() >= 1);
}
// 测试注销

View File

@ -68,7 +68,7 @@ public class JwtForSimpleTest {
SaSession session = dao.getSession("satoken:login:session:" + 10001);
Assertions.assertNotNull(session);
Assertions.assertEquals(session.getId(), "satoken:login:session:" + 10001);
Assertions.assertTrue(session.getTokenSignList().size() >= 1);
Assertions.assertTrue(session.getTerminalList().size() >= 1);
}
// 测试getExtra

View File

@ -61,7 +61,7 @@ public class JwtForStatelessTest {
JWT jwt = JWT.of(token);
JSONObject payloads = jwt.getPayloads();
Assertions.assertEquals(payloads.getStr(SaJwtUtil.LOGIN_ID), "10001"); // 账号
Assertions.assertEquals(payloads.getStr(SaJwtUtil.DEVICE), SaTokenConsts.DEFAULT_LOGIN_DEVICE); // 登录设备类型
Assertions.assertEquals(payloads.getStr(SaJwtUtil.DEVICE_TYPE), SaTokenConsts.DEFAULT_LOGIN_DEVICE); // 登录设备类型
Assertions.assertEquals(payloads.getStr(SaJwtUtil.LOGIN_TYPE), StpUtil.TYPE); // 账号类型
// 时间

View File

@ -15,18 +15,17 @@
*/
package cn.dev33.satoken.core.session;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.session.SaTerminalInfo;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.session.TokenSign;
/**
* SaSession 测试
*
@ -112,33 +111,33 @@ public class SaSessionTest {
SaSession session = new SaSession("session-1002");
// 添加 Token 签名
session.addTokenSign(new TokenSign("xxxx-xxxx-xxxx-xxxx-1", "PC", null));
session.addTokenSign(new TokenSign("xxxx-xxxx-xxxx-xxxx-2", "APP", null));
session.addTerminal(new SaTerminalInfo(1, "xxxx-xxxx-xxxx-xxxx-1", "PC", null));
session.addTerminal(new SaTerminalInfo(2, "xxxx-xxxx-xxxx-xxxx-2", "APP", null));
// 查询
Assertions.assertEquals(session.getTokenSignList().size(), 2);
Assertions.assertEquals(session.getTokenSign("xxxx-xxxx-xxxx-xxxx-1").getDevice(), "PC");
Assertions.assertEquals(session.getTokenSign("xxxx-xxxx-xxxx-xxxx-2").getDevice(), "APP");
Assertions.assertEquals(session.getTerminalList().size(), 2);
Assertions.assertEquals(session.getTerminal("xxxx-xxxx-xxxx-xxxx-1").getDeviceType(), "PC");
Assertions.assertEquals(session.getTerminal("xxxx-xxxx-xxxx-xxxx-2").getDeviceType(), "APP");
// 删除一个
session.removeTokenSign("xxxx-xxxx-xxxx-xxxx-1");
Assertions.assertEquals(session.getTokenSignList().size(), 1);
session.removeTerminal("xxxx-xxxx-xxxx-xxxx-1");
Assertions.assertEquals(session.getTerminalList().size(), 1);
// 删除一个不存在的则不影响 TokenSign 列表
session.removeTokenSign("xxxx-xxxx-xxxx-xxxx-999");
Assertions.assertEquals(session.getTokenSignList().size(), 1);
session.removeTerminal("xxxx-xxxx-xxxx-xxxx-999");
Assertions.assertEquals(session.getTerminalList().size(), 1);
// 重置整个签名列表
List<TokenSign> list = Arrays.asList(
new TokenSign("xxxx-xxxx-xxxx-xxxx-1", "WEB", null),
new TokenSign("xxxx-xxxx-xxxx-xxxx-2", "phone", null),
new TokenSign("xxxx-xxxx-xxxx-xxxx-3", "ipad", null)
List<SaTerminalInfo> list = Arrays.asList(
new SaTerminalInfo(1, "xxxx-xxxx-xxxx-xxxx-1", "WEB", null),
new SaTerminalInfo(2, "xxxx-xxxx-xxxx-xxxx-2", "phone", null),
new SaTerminalInfo(3, "xxxx-xxxx-xxxx-xxxx-3", "ipad", null)
);
session.setTokenSignList(list);
Assertions.assertEquals(session.getTokenSignList().size(), 3);
Assertions.assertEquals(session.getTokenSign("xxxx-xxxx-xxxx-xxxx-1").getDevice(), "WEB");
Assertions.assertEquals(session.getTokenSign("xxxx-xxxx-xxxx-xxxx-2").getDevice(), "phone");
Assertions.assertEquals(session.getTokenSign("xxxx-xxxx-xxxx-xxxx-3").getDevice(), "ipad");
session.setTerminalList(list);
Assertions.assertEquals(session.getTerminalList().size(), 3);
Assertions.assertEquals(session.getTerminal("xxxx-xxxx-xxxx-xxxx-1").getDeviceType(), "WEB");
Assertions.assertEquals(session.getTerminal("xxxx-xxxx-xxxx-xxxx-2").getDeviceType(), "phone");
Assertions.assertEquals(session.getTerminal("xxxx-xxxx-xxxx-xxxx-3").getDeviceType(), "ipad");
}
// 测试重置 DataMap

View File

@ -15,28 +15,27 @@
*/
package cn.dev33.satoken.core.session;
import cn.dev33.satoken.session.SaTerminalInfo;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import cn.dev33.satoken.session.TokenSign;
/**
* TokenSign 相关测试
*
* @author click33
* @since 2022-9-4
*/
public class TokenSignTest {
public class SaTerminalInfoTest {
// 测试
@Test
public void testTokenSign() {
TokenSign tokenSign = new TokenSign();
tokenSign.setDevice("PC");
tokenSign.setValue("ttt-value");
public void testSaTerminalInfo() {
SaTerminalInfo tokenSign = new SaTerminalInfo();
tokenSign.setDeviceType("PC");
tokenSign.setTokenValue("ttt-value");
Assertions.assertEquals(tokenSign.getDevice(), "PC");
Assertions.assertEquals(tokenSign.getValue(), "ttt-value");
Assertions.assertEquals(tokenSign.getDeviceType(), "PC");
Assertions.assertEquals(tokenSign.getTokenValue(), "ttt-value");
Assertions.assertNotNull(tokenSign.toString());
}

View File

@ -44,7 +44,7 @@ public class TokenInfoTest {
info.setSessionTimeout(120);
info.setTokenSessionTimeout(1800);
info.setTokenActiveTimeout(120);
info.setLoginDevice("PC");
info.setLoginDeviceType("PC");
info.setTag("xxx");
Assertions.assertEquals(info.getTokenName(), "satoken");
@ -56,7 +56,7 @@ public class TokenInfoTest {
Assertions.assertEquals(info.getSessionTimeout(), 120);
Assertions.assertEquals(info.getTokenSessionTimeout(), 1800);
Assertions.assertEquals(info.getTokenActiveTimeout(), 120);
Assertions.assertEquals(info.getLoginDevice(), "PC");
Assertions.assertEquals(info.getLoginDeviceType(), "PC");
Assertions.assertEquals(info.getTag(), "xxx");
Assertions.assertNotNull(info.toString());
@ -64,7 +64,7 @@ public class TokenInfoTest {
@Test
public void testLoginParameter() {
Assertions.assertEquals(new SaLoginParameter().setDevice("PC").getDevice(), "PC");
Assertions.assertEquals(new SaLoginParameter().setDeviceType("PC").getDeviceType(), "PC");
Assertions.assertEquals(new SaLoginParameter().setIsLastingCookie(false).getIsLastingCookie(), false);
Assertions.assertEquals(new SaLoginParameter().setTimeout(1600).getTimeout(), 1600);
Assertions.assertEquals(new SaLoginParameter().setToken("token-xxx").getToken(), "token-xxx");

View File

@ -128,7 +128,7 @@ public class BasicsTest {
SaSession session = dao.getSession("satoken:login:session:" + 10001);
Assertions.assertNotNull(session);
Assertions.assertEquals(session.getId(), "satoken:login:session:" + 10001);
Assertions.assertTrue(session.getTokenSignList().size() >= 1);
Assertions.assertTrue(session.getTerminalList().size() >= 1);
}
// 测试注销

View File

@ -15,8 +15,12 @@
*/
package cn.dev33.satoken.springboot;
import java.util.List;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.session.SaTerminalInfo;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
@ -24,12 +28,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.session.TokenSign;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
import java.util.List;
/**
* Sa-Token 多端登录测试
@ -115,9 +114,9 @@ public class ManyLoginTest {
Assertions.assertEquals(dao.get("satoken:login:token:" + token1), "-4");
// Account-Session里的 token1 签名会被移除
List<TokenSign> tokenSignList = StpUtil.getSessionByLoginId(10001).getTokenSignList();
for (TokenSign tokenSign : tokenSignList) {
Assertions.assertNotEquals(tokenSign.getValue(), token1);
List<SaTerminalInfo> tokenSignList = StpUtil.getSessionByLoginId(10001).getTerminalList();
for (SaTerminalInfo terminal : tokenSignList) {
Assertions.assertNotEquals(terminal.getTokenValue(), token1);
}
}