mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-09-19 18:22:15 +08:00
新增Sa-Id模块,解决微服务内部调用鉴权问题
This commit is contained in:
@@ -18,7 +18,7 @@ public class SaTokenConfig implements Serializable {
|
||||
private String tokenName = "satoken";
|
||||
|
||||
/** token的长久有效期(单位:秒) 默认30天, -1代表永久 */
|
||||
private long timeout = 30 * 24 * 60 * 60;
|
||||
private long timeout = 60 * 60 * 24 * 30;
|
||||
|
||||
/**
|
||||
* token临时有效期 [指定时间内无操作就视为token过期] (单位: 秒), 默认-1 代表不限制
|
||||
@@ -70,6 +70,12 @@ public class SaTokenConfig implements Serializable {
|
||||
*/
|
||||
private String jwtSecretKey;
|
||||
|
||||
/**
|
||||
* Id-Token的有效期 (单位: 秒)
|
||||
*/
|
||||
private long idTokenTimeout = 60 * 60 * 24;
|
||||
|
||||
|
||||
/**
|
||||
* SSO单点登录配置对象
|
||||
*/
|
||||
@@ -352,6 +358,22 @@ public class SaTokenConfig implements Serializable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Id-Token的有效期 (单位: 秒)
|
||||
*/
|
||||
public long getIdTokenTimeout() {
|
||||
return idTokenTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param idTokenTimeout Id-Token的有效期 (单位: 秒)
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaTokenConfig setIdTokenTimeout(long idTokenTimeout) {
|
||||
this.idTokenTimeout = idTokenTimeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SSO单点登录配置对象
|
||||
*/
|
||||
@@ -359,7 +381,6 @@ public class SaTokenConfig implements Serializable {
|
||||
return sso;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param sso SSO单点登录配置对象
|
||||
*/
|
||||
@@ -367,19 +388,15 @@ public class SaTokenConfig implements Serializable {
|
||||
this.sso = sso;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SaTokenConfig [tokenName=" + tokenName + ", timeout=" + timeout + ", activityTimeout=" + activityTimeout
|
||||
+ ", isConcurrent=" + isConcurrent + ", isShare=" + isShare + ", isReadBody="
|
||||
+ isReadBody + ", isReadHead=" + isReadHead + ", isReadCookie=" + isReadCookie + ", tokenStyle="
|
||||
+ tokenStyle + ", dataRefreshPeriod=" + dataRefreshPeriod + ", tokenSessionCheckLogin="
|
||||
+ tokenSessionCheckLogin + ", autoRenew=" + autoRenew + ", cookieDomain=" + cookieDomain
|
||||
+ ", tokenPrefix=" + tokenPrefix + ", isPrint=" + isPrint + ", isLog=" + isLog + ", jwtSecretKey="
|
||||
+ jwtSecretKey + ", sso=" + sso + "]";
|
||||
+ ", isConcurrent=" + isConcurrent + ", isShare=" + isShare + ", isReadBody=" + isReadBody
|
||||
+ ", isReadHead=" + isReadHead + ", isReadCookie=" + isReadCookie + ", tokenStyle=" + tokenStyle
|
||||
+ ", dataRefreshPeriod=" + dataRefreshPeriod + ", tokenSessionCheckLogin=" + tokenSessionCheckLogin
|
||||
+ ", autoRenew=" + autoRenew + ", cookieDomain=" + cookieDomain + ", tokenPrefix=" + tokenPrefix
|
||||
+ ", isPrint=" + isPrint + ", isLog=" + isLog + ", jwtSecretKey=" + jwtSecretKey + ", idTokenTimeout="
|
||||
+ idTokenTimeout + ", sso=" + sso + "]";
|
||||
}
|
||||
|
||||
|
||||
|
@@ -0,0 +1,22 @@
|
||||
package cn.dev33.satoken.exception;
|
||||
|
||||
/**
|
||||
* 一个异常:代表提供的 Id-Token 无效
|
||||
*
|
||||
* @author kong
|
||||
*/
|
||||
public class IdTokenInvalidException extends SaTokenException {
|
||||
|
||||
/**
|
||||
* 序列化版本号
|
||||
*/
|
||||
private static final long serialVersionUID = 6806129545290130144L;
|
||||
|
||||
/**
|
||||
* 一个异常:代表提供的 Id-Token 无效
|
||||
*/
|
||||
public IdTokenInvalidException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,172 @@
|
||||
package cn.dev33.satoken.id;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import cn.dev33.satoken.exception.IdTokenInvalidException;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
|
||||
/**
|
||||
* Sa-Token-Id 身份凭证模块
|
||||
* <p> 身份凭证的获取与校验,可用于微服务内部调用鉴权
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaIdTemplate {
|
||||
|
||||
/**
|
||||
* 在 Request 上储存 Id-Token 时建议使用的key
|
||||
*/
|
||||
public static final String ID_TOKEN = "SA_ID_TOKEN";
|
||||
|
||||
// -------------------- 获取 & 校验
|
||||
|
||||
/**
|
||||
* 获取当前Id-Token, 如果不存在,则立即创建并返回
|
||||
* @return 当前token
|
||||
*/
|
||||
public String getToken() {
|
||||
String currentToken = getTokenNh();
|
||||
if(SaFoxUtil.isEmpty(currentToken)) {
|
||||
// 注意这里的自刷新不能做到高并发可用
|
||||
currentToken = refreshToken();
|
||||
}
|
||||
return currentToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断一个Id-Token是否有效
|
||||
* @param token 要验证的token
|
||||
* @return 这个token是否有效
|
||||
*/
|
||||
public boolean isValid(String token) {
|
||||
// 1、 如果传入的token未空,立即返回false
|
||||
if(SaFoxUtil.isEmpty(token)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2、 验证当前 Id-Token 及 Past-Id-Token
|
||||
return token.equals(getToken()) || token.equals(getPastTokenNh());
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验一个Id-Token是否有效 (如果无效则抛出异常)
|
||||
* @param token 要验证的token
|
||||
*/
|
||||
public void checkToken(String token) {
|
||||
if(isValid(token) == false) {
|
||||
token = (token == null ? "" : token);
|
||||
throw new IdTokenInvalidException("无效Id-Token:" + token);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验当前Request提供的Id-Token是否有效 (如果无效则抛出异常)
|
||||
*/
|
||||
public void checkCurrentRequestToken() {
|
||||
checkToken(SaHolder.getRequest().getHeader(ID_TOKEN));
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新一次Id-Token (注意集群环境中不要多个服务重复调用)
|
||||
* @return 新Token
|
||||
*/
|
||||
public String refreshToken() {
|
||||
|
||||
// 1. 先将当前 Id-Token 写入到 Past-Id-Token 中
|
||||
String idToken = getTokenNh();
|
||||
if(SaFoxUtil.isEmpty(idToken) == false) {
|
||||
savePastToken(idToken, getTokenTimeout());
|
||||
}
|
||||
|
||||
// 2. 再刷新当前Id-Token
|
||||
String newIdToken = createToken();
|
||||
saveToken(newIdToken);
|
||||
|
||||
// 3. 返回新的 Id-Token
|
||||
return newIdToken;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------ 保存Token
|
||||
|
||||
/**
|
||||
* 保存Id-Token
|
||||
* @param token
|
||||
*/
|
||||
public void saveToken(String token) {
|
||||
if(SaFoxUtil.isEmpty(token)) {
|
||||
return;
|
||||
}
|
||||
SaManager.getSaTokenDao().set(splicingTokenSaveKey(), token, SaManager.getConfig().getIdTokenTimeout());
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存Past-Id-Token
|
||||
* @param token token
|
||||
* @param timeout 有效期(单位:秒)
|
||||
*/
|
||||
public void savePastToken(String token, long timeout){
|
||||
if(SaFoxUtil.isEmpty(token)) {
|
||||
return;
|
||||
}
|
||||
SaManager.getSaTokenDao().set(splicingPastTokenSaveKey(), token, timeout);
|
||||
}
|
||||
|
||||
|
||||
// -------------------- 获取Token
|
||||
|
||||
/**
|
||||
* 获取Id-Token,不做任何处理
|
||||
* @return token
|
||||
*/
|
||||
public String getTokenNh() {
|
||||
return SaManager.getSaTokenDao().get(splicingTokenSaveKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Past-Id-Token,不做任何处理
|
||||
* @return token
|
||||
*/
|
||||
public String getPastTokenNh() {
|
||||
return SaManager.getSaTokenDao().get(splicingPastTokenSaveKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Id-Token的剩余有效期 (单位:秒)
|
||||
* @return token
|
||||
*/
|
||||
public long getTokenTimeout() {
|
||||
return SaManager.getSaTokenDao().getTimeout(splicingTokenSaveKey());
|
||||
}
|
||||
|
||||
|
||||
// -------------------- 创建Token
|
||||
|
||||
/**
|
||||
* 创建一个Id-Token
|
||||
* @return Token
|
||||
*/
|
||||
public String createToken() {
|
||||
return SaFoxUtil.getRandomString(60);
|
||||
}
|
||||
|
||||
|
||||
// -------------------- 拼接key
|
||||
|
||||
/**
|
||||
* 拼接key:Id-Token的存储key
|
||||
* @return key
|
||||
*/
|
||||
public String splicingTokenSaveKey() {
|
||||
return SaManager.getConfig().getTokenName() + ":var:id-token";
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接key:Id-Token的存储key
|
||||
* @return key
|
||||
*/
|
||||
public String splicingPastTokenSaveKey() {
|
||||
return SaManager.getConfig().getTokenName() + ":var:past-id-token";
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
package cn.dev33.satoken.id;
|
||||
|
||||
/**
|
||||
* Sa-Token-Id 身份凭证模块-工具类
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaIdUtil {
|
||||
|
||||
/**
|
||||
* 在 Request 上储存 Id-Token 时建议使用的key
|
||||
*/
|
||||
public static final String ID_TOKEN = SaIdTemplate.ID_TOKEN;
|
||||
|
||||
/**
|
||||
* 底层 SaIdTemplate 对象
|
||||
*/
|
||||
public static SaIdTemplate saIdTemplate = new SaIdTemplate();
|
||||
|
||||
// -------------------- 获取 & 校验
|
||||
|
||||
/**
|
||||
* 获取当前Id-Token, 如果不存在,则立即创建并返回
|
||||
* @return 当前token
|
||||
*/
|
||||
public static String getToken() {
|
||||
return saIdTemplate.getToken();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断一个Id-Token是否有效
|
||||
* @param token 要验证的token
|
||||
* @return 这个token是否有效
|
||||
*/
|
||||
public static boolean isValid(String token) {
|
||||
return saIdTemplate.isValid(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验一个Id-Token是否有效 (如果无效则抛出异常)
|
||||
* @param token 要验证的token
|
||||
*/
|
||||
public static void checkToken(String token) {
|
||||
saIdTemplate.checkToken(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验当前Request提供的Id-Token是否有效 (如果无效则抛出异常)
|
||||
*/
|
||||
public static void checkCurrentRequestToken() {
|
||||
saIdTemplate.checkCurrentRequestToken();
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新一次Id-Token (注意集群环境中不要多个服务重复调用)
|
||||
* @return 新Token
|
||||
*/
|
||||
public static String refreshToken() {
|
||||
return saIdTemplate.refreshToken();
|
||||
}
|
||||
|
||||
|
||||
// -------------------- 获取Token
|
||||
|
||||
/**
|
||||
* 获取Id-Token,不做任何处理
|
||||
* @return token
|
||||
*/
|
||||
public static String getTokenNh() {
|
||||
return saIdTemplate.getTokenNh();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Past-Id-Token,不做任何处理
|
||||
* @return token
|
||||
*/
|
||||
public static String getPastTokenNh() {
|
||||
return saIdTemplate.getPastTokenNh();
|
||||
}
|
||||
|
||||
}
|
@@ -13,7 +13,7 @@ import cn.dev33.satoken.stp.StpLogic;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
|
||||
/**
|
||||
* Sa-Token-SSO 单点登录接口
|
||||
* Sa-Token-SSO 单点登录模块
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
|
Reference in New Issue
Block a user