mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-10-27 02:59:02 +08:00
重构 sa-token-jwt 模块
This commit is contained in:
@@ -1,16 +1,18 @@
|
||||
package cn.dev33.satoken.jwt;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import cn.dev33.satoken.dao.SaTokenDao;
|
||||
import cn.dev33.satoken.exception.NotLoginException;
|
||||
import cn.dev33.satoken.jwt.exception.SaJwtException;
|
||||
import cn.dev33.satoken.jwt.exception.SaJwtExceptionCode;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.jwt.JWT;
|
||||
import cn.hutool.jwt.JWTException;
|
||||
|
||||
/**
|
||||
* jwt操作工具类封装
|
||||
* jwt 操作工具类封装
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
@@ -36,27 +38,38 @@ public class SaJwtUtil {
|
||||
*/
|
||||
public static final String EFF = "eff";
|
||||
|
||||
/**
|
||||
* key:乱数 ( 混入随机字符串,防止每次生成的 token 都是一样的 )
|
||||
*/
|
||||
public static final String RN_STR = "rnStr";
|
||||
|
||||
/**
|
||||
* 当有效期被设为此值时,代表永不过期
|
||||
*/
|
||||
public static final long NEVER_EXPIRE = SaTokenDao.NEVER_EXPIRE;
|
||||
|
||||
/**
|
||||
* 表示一个值不存在
|
||||
*/
|
||||
public static final long NOT_VALUE_EXPIRE = SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
|
||||
// ------ 创建
|
||||
|
||||
/**
|
||||
* 创建 jwt (简单方式)
|
||||
* @param loginType 登录类型
|
||||
* @param loginId 账号id
|
||||
* @param extraData 扩展数据
|
||||
* @param keyt 秘钥
|
||||
* @return jwt-token
|
||||
*/
|
||||
public static String createToken(Object loginId, Map<String, Object> extraData, String keyt) {
|
||||
public static String createToken(String loginType, Object loginId, Map<String, Object> extraData, String keyt) {
|
||||
|
||||
// 构建
|
||||
String token = JWT.create()
|
||||
.setPayload(LOGIN_TYPE, loginType)
|
||||
.setPayload(LOGIN_ID, loginId)
|
||||
// 混入随机字符串,防止每次生成的 token 都是一样的
|
||||
.setPayload("rn", SaFoxUtil.getRandomString(32))
|
||||
.setPayload(RN_STR, SaFoxUtil.getRandomString(32))
|
||||
.addPayloads(extraData)
|
||||
.setKey(keyt.getBytes())
|
||||
.sign();
|
||||
@@ -90,6 +103,7 @@ public class SaJwtUtil {
|
||||
.setPayload(LOGIN_ID, loginId)
|
||||
.setPayload(DEVICE, device)
|
||||
.setPayload(EFF, effTime)
|
||||
.setPayload(RN_STR, SaFoxUtil.getRandomString(32))
|
||||
.addPayloads(extraData);
|
||||
|
||||
// 返回
|
||||
@@ -99,16 +113,18 @@ public class SaJwtUtil {
|
||||
// ------ 解析
|
||||
|
||||
/**
|
||||
* jwt 解析(校验签名和有效期)
|
||||
* jwt 解析
|
||||
* @param token Jwt-Token值
|
||||
* @param loginType 登录类型
|
||||
* @param keyt 秘钥
|
||||
* @param isCheckTimeout 是否校验 timeout 字段
|
||||
* @return 解析后的jwt 对象
|
||||
*/
|
||||
public static JWT parseToken(String token, String keyt) {
|
||||
public static JWT parseToken(String token, String loginType, String keyt, boolean isCheckTimeout) {
|
||||
|
||||
// 如果token为null
|
||||
if(token == null) {
|
||||
throw NotLoginException.newInstance(null, NotLoginException.NOT_TOKEN);
|
||||
throw new SaJwtException("jwt 字符串不可为空");
|
||||
}
|
||||
|
||||
// 解析
|
||||
@@ -116,23 +132,29 @@ public class SaJwtUtil {
|
||||
try {
|
||||
jwt = JWT.of(token);
|
||||
} catch (JWTException e) {
|
||||
// 解析失败
|
||||
throw NotLoginException.newInstance(null, NotLoginException.INVALID_TOKEN, token);
|
||||
throw new SaJwtException("jwt 解析失败:" + token, e).setCode(SaJwtExceptionCode.CODE_40101);
|
||||
}
|
||||
JSONObject payloads = jwt.getPayloads();
|
||||
|
||||
// 校验 Token 签名
|
||||
boolean verify = jwt.setKey(keyt.getBytes()).verify();
|
||||
if(verify == false) {
|
||||
throw NotLoginException.newInstance(payloads.getStr(LOGIN_TYPE), NotLoginException.INVALID_TOKEN, token);
|
||||
throw new SaJwtException("jwt 签名无效:" + token).setCode(SaJwtExceptionCode.CODE_40102);
|
||||
};
|
||||
|
||||
// 校验 loginType
|
||||
if(Objects.equals(loginType, payloads.getStr(LOGIN_TYPE)) == false) {
|
||||
throw new SaJwtException("jwt loginType 无效:" + token).setCode(SaJwtExceptionCode.CODE_40103);
|
||||
}
|
||||
|
||||
// 校验 Token 有效期
|
||||
Long effTime = payloads.getLong(EFF, 0L);
|
||||
if(effTime != NEVER_EXPIRE) {
|
||||
if(effTime == null || effTime < System.currentTimeMillis()) {
|
||||
throw NotLoginException.newInstance(payloads.getStr(LOGIN_TYPE), NotLoginException.TOKEN_TIMEOUT, token);
|
||||
}
|
||||
if(isCheckTimeout) {
|
||||
Long effTime = payloads.getLong(EFF, 0L);
|
||||
if(effTime != NEVER_EXPIRE) {
|
||||
if(effTime == null || effTime < System.currentTimeMillis()) {
|
||||
throw new SaJwtException("jwt 已过期:" + token).setCode(SaJwtExceptionCode.CODE_40104);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 返回
|
||||
@@ -140,58 +162,49 @@ public class SaJwtUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 jwt 数据载荷 (校验签名和有效期)
|
||||
* 获取 jwt 数据载荷 (校验 sign、loginType、timeout)
|
||||
* @param token token值
|
||||
* @param loginType 登录类型
|
||||
* @param keyt 秘钥
|
||||
* @return 载荷
|
||||
*/
|
||||
public static JSONObject getPayloads(String token, String keyt) {
|
||||
return parseToken(token, keyt).getPayloads();
|
||||
public static JSONObject getPayloads(String token, String loginType, String keyt) {
|
||||
return parseToken(token, loginType, keyt, true).getPayloads();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 jwt 数据载荷 (只校验签名,不校验有效期)
|
||||
* 获取 jwt 数据载荷 (校验 sign、loginType,不校验 timeout)
|
||||
* @param token token值
|
||||
* @param loginType 登录类型
|
||||
* @param keyt 秘钥
|
||||
* @return 载荷
|
||||
*/
|
||||
public static JSONObject getPayloadsNotCheck(String token, String keyt) {
|
||||
try {
|
||||
JWT jwt = JWT.of(token);
|
||||
JSONObject payloads = jwt.getPayloads();
|
||||
|
||||
// 校验 Token 签名
|
||||
boolean verify = jwt.setKey(keyt.getBytes()).verify();
|
||||
if(verify == false) {
|
||||
throw NotLoginException.newInstance(payloads.getStr(LOGIN_TYPE), NotLoginException.INVALID_TOKEN, token);
|
||||
};
|
||||
|
||||
return payloads;
|
||||
} catch (JWTException e) {
|
||||
return new JSONObject();
|
||||
}
|
||||
public static JSONObject getPayloadsNotCheck(String token, String loginType, String keyt) {
|
||||
return parseToken(token, loginType, keyt, false).getPayloads();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 jwt 代表的账号id
|
||||
* @param token Token值
|
||||
* @param loginType 登录类型
|
||||
* @param keyt 秘钥
|
||||
* @return 值
|
||||
*/
|
||||
public static Object getLoginId(String token, String keyt) {
|
||||
return getPayloads(token, keyt).get(LOGIN_ID);
|
||||
public static Object getLoginId(String token, String loginType, String keyt) {
|
||||
return getPayloads(token, loginType, keyt).get(LOGIN_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 jwt 代表的账号id (未登录时返回null)
|
||||
* @param token Token值
|
||||
* @param loginType 登录类型
|
||||
* @param keyt 秘钥
|
||||
* @return 值
|
||||
*/
|
||||
public static Object getLoginIdOrNull(String token, String keyt) {
|
||||
public static Object getLoginIdOrNull(String token, String loginType, String keyt) {
|
||||
try {
|
||||
return getPayloads(token, keyt).get(LOGIN_ID);
|
||||
} catch (NotLoginException e) {
|
||||
return getPayloads(token, loginType, keyt).get(LOGIN_ID);
|
||||
} catch (SaJwtException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -199,14 +212,15 @@ public class SaJwtUtil {
|
||||
/**
|
||||
* 获取 jwt 剩余有效期
|
||||
* @param token JwtToken值
|
||||
* @param loginType 登录类型
|
||||
* @param keyt 秘钥
|
||||
* @return 值
|
||||
*/
|
||||
public static long getTimeout(String token, String keyt) {
|
||||
public static long getTimeout(String token, String loginType, String keyt) {
|
||||
|
||||
// 如果token为null
|
||||
if(token == null) {
|
||||
return SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
return NOT_VALUE_EXPIRE;
|
||||
}
|
||||
|
||||
// 取出数据
|
||||
@@ -215,15 +229,20 @@ public class SaJwtUtil {
|
||||
jwt = JWT.of(token);
|
||||
} catch (JWTException e) {
|
||||
// 解析失败
|
||||
return SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
return NOT_VALUE_EXPIRE;
|
||||
}
|
||||
JSONObject payloads = jwt.getPayloads();
|
||||
|
||||
// 如果签名无效
|
||||
boolean verify = jwt.setKey(keyt.getBytes()).verify();
|
||||
if(verify == false) {
|
||||
return SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
return NOT_VALUE_EXPIRE;
|
||||
};
|
||||
|
||||
// 如果 loginType 无效
|
||||
if(Objects.equals(loginType, payloads.getStr(LOGIN_TYPE)) == false) {
|
||||
return NOT_VALUE_EXPIRE;
|
||||
}
|
||||
|
||||
// 如果被设置为:永不过期
|
||||
Long effTime = payloads.get(EFF, Long.class);
|
||||
@@ -232,38 +251,11 @@ public class SaJwtUtil {
|
||||
}
|
||||
// 如果已经超时
|
||||
if(effTime == null || effTime < System.currentTimeMillis()) {
|
||||
return SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
return NOT_VALUE_EXPIRE;
|
||||
}
|
||||
|
||||
// 计算timeout (转化为以秒为单位的有效时间)
|
||||
return (effTime - System.currentTimeMillis()) / 1000;
|
||||
}
|
||||
|
||||
// ------ 废弃API
|
||||
|
||||
/**
|
||||
* 创建 jwt (简单方式)
|
||||
* @param loginId 账号id
|
||||
* @param keyt 秘钥
|
||||
* @return jwt-token
|
||||
*/
|
||||
@Deprecated
|
||||
public static String createToken(Object loginId, String keyt) {
|
||||
return createToken(loginId, null, keyt);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 jwt (全参数方式)
|
||||
* @param loginType 账号类型
|
||||
* @param loginId 账号id
|
||||
* @param device 设备类型
|
||||
* @param timeout token有效期 (单位 秒)
|
||||
* @param keyt 秘钥
|
||||
* @return jwt-token
|
||||
*/
|
||||
@Deprecated
|
||||
public static String createToken(String loginType, Object loginId, String device, long timeout, String keyt) {
|
||||
return createToken(loginType, loginId, device, timeout, null, keyt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,221 +1,12 @@
|
||||
package cn.dev33.satoken.jwt;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import cn.dev33.satoken.dao.SaTokenDao;
|
||||
import cn.dev33.satoken.exception.ApiDisabledException;
|
||||
import cn.dev33.satoken.exception.NotLoginException;
|
||||
import cn.dev33.satoken.exception.SaTokenException;
|
||||
import cn.dev33.satoken.stp.SaTokenInfo;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
|
||||
/**
|
||||
* Sa-Token 整合 jwt -- Mix 混入
|
||||
* 已更名为 StpLogicJwtForMixin,请更换
|
||||
*
|
||||
* @author kong
|
||||
*
|
||||
* @date: 2022-5-1
|
||||
*/
|
||||
public class StpLogicJwtForMix extends StpLogic {
|
||||
@Deprecated
|
||||
public class StpLogicJwtForMix extends StpLogicJwtForMixin {
|
||||
|
||||
/**
|
||||
* Sa-Token 整合 jwt -- Mix 混入
|
||||
*/
|
||||
public StpLogicJwtForMix() {
|
||||
super(StpUtil.TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sa-Token 整合 jwt -- Mix 混入
|
||||
* @param loginType 账号体系标识
|
||||
*/
|
||||
public StpLogicJwtForMix(String loginType) {
|
||||
super(loginType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取jwt秘钥
|
||||
* @return /
|
||||
*/
|
||||
public String jwtSecretKey() {
|
||||
String keyt = getConfig().getJwtSecretKey();
|
||||
SaTokenException.throwByNull(keyt, "请配置jwt秘钥");
|
||||
return keyt;
|
||||
}
|
||||
|
||||
//
|
||||
// ------ 重写方法
|
||||
//
|
||||
|
||||
// ------------------- 获取token 相关 -------------------
|
||||
|
||||
/**
|
||||
* 创建一个TokenValue
|
||||
*/
|
||||
@Override
|
||||
public String createTokenValue(Object loginId, String device, long timeout, Map<String, Object> extraData) {
|
||||
return SaJwtUtil.createToken(loginType, loginId, device, timeout, extraData, jwtSecretKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会话的Token信息
|
||||
* @return token信息
|
||||
*/
|
||||
@Override
|
||||
public SaTokenInfo getTokenInfo() {
|
||||
SaTokenInfo info = new SaTokenInfo();
|
||||
info.tokenName = getTokenName();
|
||||
info.tokenValue = getTokenValue();
|
||||
info.isLogin = isLogin();
|
||||
info.loginId = getLoginIdDefaultNull();
|
||||
info.loginType = getLoginType();
|
||||
info.tokenTimeout = getTokenTimeout();
|
||||
info.sessionTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
info.tokenSessionTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
info.tokenActivityTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
info.loginDevice = getLoginDevice();
|
||||
return info;
|
||||
}
|
||||
|
||||
// ------------------- 登录相关操作 -------------------
|
||||
|
||||
/**
|
||||
* 获取指定Token对应的账号id (不做任何特殊处理)
|
||||
*/
|
||||
@Override
|
||||
public String getLoginIdNotHandle(String tokenValue) {
|
||||
// 先验证 loginType,如果不符,则视为无效token,返回null
|
||||
String loginType = SaJwtUtil.getPayloadsNotCheck(tokenValue, jwtSecretKey()).getStr(SaJwtUtil.LOGIN_TYPE);
|
||||
if(getLoginType().equals(loginType) == false) {
|
||||
return null;
|
||||
}
|
||||
// 获取 loginId
|
||||
try {
|
||||
Object loginId = SaJwtUtil.getLoginId(tokenValue, jwtSecretKey());
|
||||
return String.valueOf(loginId);
|
||||
} catch (NotLoginException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 会话注销
|
||||
*/
|
||||
@Override
|
||||
public void logout() {
|
||||
// ...
|
||||
|
||||
// 从当前 [storage存储器] 里删除
|
||||
SaHolder.getStorage().delete(splicingKeyJustCreatedSave());
|
||||
|
||||
// 如果打开了Cookie模式,则把cookie清除掉
|
||||
if(getConfig().getIsReadCookie()){
|
||||
SaHolder.getResponse().deleteCookie(getTokenName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [禁用] 会话注销,根据账号id 和 设备类型
|
||||
*/
|
||||
@Override
|
||||
public void logout(Object loginId, String device) {
|
||||
throw new ApiDisabledException();
|
||||
}
|
||||
|
||||
/**
|
||||
* [禁用] 会话注销,根据指定 Token
|
||||
*/
|
||||
@Override
|
||||
public void logoutByTokenValue(String tokenValue) {
|
||||
throw new ApiDisabledException();
|
||||
}
|
||||
|
||||
/**
|
||||
* [禁用] 踢人下线,根据账号id 和 设备类型
|
||||
*/
|
||||
@Override
|
||||
public void kickout(Object loginId, String device) {
|
||||
throw new ApiDisabledException();
|
||||
}
|
||||
|
||||
/**
|
||||
* [禁用] 踢人下线,根据指定 Token
|
||||
*/
|
||||
@Override
|
||||
public void kickoutByTokenValue(String tokenValue) {
|
||||
throw new ApiDisabledException();
|
||||
}
|
||||
|
||||
/**
|
||||
* [禁用] 顶人下线,根据账号id 和 设备类型
|
||||
*/
|
||||
@Override
|
||||
public void replaced(Object loginId, String device) {
|
||||
throw new ApiDisabledException();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Token携带的扩展信息
|
||||
*/
|
||||
@Override
|
||||
public Object getExtra(String key) {
|
||||
return SaJwtUtil.getPayloads(getTokenValue(), jwtSecretKey()).get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除 Token-Id 映射
|
||||
*/
|
||||
@Override
|
||||
public void deleteTokenToIdMapping(String tokenValue) {
|
||||
// not action
|
||||
}
|
||||
/**
|
||||
* 更改 Token 指向的 账号Id 值
|
||||
*/
|
||||
@Override
|
||||
public void updateTokenToIdMapping(String tokenValue, Object loginId) {
|
||||
// not action
|
||||
}
|
||||
/**
|
||||
* 存储 Token-Id 映射
|
||||
*/
|
||||
@Override
|
||||
public void saveTokenToIdMapping(String tokenValue, Object loginId, long timeout) {
|
||||
// not action
|
||||
}
|
||||
|
||||
// ------------------- 过期时间相关 -------------------
|
||||
|
||||
/**
|
||||
* 获取当前登录者的 token 剩余有效时间 (单位: 秒)
|
||||
*/
|
||||
@Override
|
||||
public long getTokenTimeout() {
|
||||
return SaJwtUtil.getTimeout(getTokenValue(), jwtSecretKey());
|
||||
}
|
||||
|
||||
|
||||
// ------------------- 会话管理 -------------------
|
||||
|
||||
/**
|
||||
* [禁用] 根据条件查询Token
|
||||
*/
|
||||
@Override
|
||||
public List<String> searchTokenValue(String keyword, int start, int size) {
|
||||
throw new ApiDisabledException();
|
||||
}
|
||||
|
||||
|
||||
// ------------------- Bean对象代理 -------------------
|
||||
|
||||
/**
|
||||
* 返回全局配置对象的isShare属性
|
||||
* @return /
|
||||
*/
|
||||
@Override
|
||||
public boolean getConfigOfIsShare() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
package cn.dev33.satoken.jwt;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import cn.dev33.satoken.dao.SaTokenDao;
|
||||
import cn.dev33.satoken.exception.ApiDisabledException;
|
||||
import cn.dev33.satoken.exception.SaTokenException;
|
||||
import cn.dev33.satoken.jwt.exception.SaJwtException;
|
||||
import cn.dev33.satoken.stp.SaTokenInfo;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
|
||||
/**
|
||||
* Sa-Token 整合 jwt -- Mixin 混入模式
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class StpLogicJwtForMixin extends StpLogic {
|
||||
|
||||
/**
|
||||
* Sa-Token 整合 jwt -- Mixin 混入
|
||||
*/
|
||||
public StpLogicJwtForMixin() {
|
||||
super(StpUtil.TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sa-Token 整合 jwt -- Mixin 混入
|
||||
* @param loginType 账号体系标识
|
||||
*/
|
||||
public StpLogicJwtForMixin(String loginType) {
|
||||
super(loginType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取jwt秘钥
|
||||
* @return /
|
||||
*/
|
||||
public String jwtSecretKey() {
|
||||
String keyt = getConfig().getJwtSecretKey();
|
||||
SaTokenException.throwByNull(keyt, "请配置jwt秘钥");
|
||||
return keyt;
|
||||
}
|
||||
|
||||
//
|
||||
// ------ 重写方法
|
||||
//
|
||||
|
||||
// ------------------- 获取token 相关 -------------------
|
||||
|
||||
/**
|
||||
* 创建一个TokenValue
|
||||
*/
|
||||
@Override
|
||||
public String createTokenValue(Object loginId, String device, long timeout, Map<String, Object> extraData) {
|
||||
return SaJwtUtil.createToken(loginType, loginId, device, timeout, extraData, jwtSecretKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会话的Token信息
|
||||
* @return token信息
|
||||
*/
|
||||
@Override
|
||||
public SaTokenInfo getTokenInfo() {
|
||||
SaTokenInfo info = new SaTokenInfo();
|
||||
info.tokenName = getTokenName();
|
||||
info.tokenValue = getTokenValue();
|
||||
info.isLogin = isLogin();
|
||||
info.loginId = getLoginIdDefaultNull();
|
||||
info.loginType = getLoginType();
|
||||
info.tokenTimeout = getTokenTimeout();
|
||||
info.sessionTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
info.tokenSessionTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
info.tokenActivityTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
info.loginDevice = getLoginDevice();
|
||||
return info;
|
||||
}
|
||||
|
||||
// ------------------- 登录相关操作 -------------------
|
||||
|
||||
/**
|
||||
* 获取指定Token对应的账号id (不做任何特殊处理)
|
||||
*/
|
||||
@Override
|
||||
public String getLoginIdNotHandle(String tokenValue) {
|
||||
try {
|
||||
Object loginId = SaJwtUtil.getLoginId(tokenValue, loginType, jwtSecretKey());
|
||||
return String.valueOf(loginId);
|
||||
} catch (SaJwtException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 会话注销
|
||||
*/
|
||||
@Override
|
||||
public void logout() {
|
||||
// ...
|
||||
|
||||
// 从当前 [storage存储器] 里删除
|
||||
SaHolder.getStorage().delete(splicingKeyJustCreatedSave());
|
||||
|
||||
// 如果打开了Cookie模式,则把cookie清除掉
|
||||
if(getConfig().getIsReadCookie()){
|
||||
SaHolder.getResponse().deleteCookie(getTokenName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [禁用] 会话注销,根据账号id 和 设备类型
|
||||
*/
|
||||
@Override
|
||||
public void logout(Object loginId, String device) {
|
||||
throw new ApiDisabledException();
|
||||
}
|
||||
|
||||
/**
|
||||
* [禁用] 会话注销,根据指定 Token
|
||||
*/
|
||||
@Override
|
||||
public void logoutByTokenValue(String tokenValue) {
|
||||
throw new ApiDisabledException();
|
||||
}
|
||||
|
||||
/**
|
||||
* [禁用] 踢人下线,根据账号id 和 设备类型
|
||||
*/
|
||||
@Override
|
||||
public void kickout(Object loginId, String device) {
|
||||
throw new ApiDisabledException();
|
||||
}
|
||||
|
||||
/**
|
||||
* [禁用] 踢人下线,根据指定 Token
|
||||
*/
|
||||
@Override
|
||||
public void kickoutByTokenValue(String tokenValue) {
|
||||
throw new ApiDisabledException();
|
||||
}
|
||||
|
||||
/**
|
||||
* [禁用] 顶人下线,根据账号id 和 设备类型
|
||||
*/
|
||||
@Override
|
||||
public void replaced(Object loginId, String device) {
|
||||
throw new ApiDisabledException();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Token携带的扩展信息
|
||||
*/
|
||||
@Override
|
||||
public Object getExtra(String key) {
|
||||
return SaJwtUtil.getPayloads(getTokenValue(), loginType, jwtSecretKey()).get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除 Token-Id 映射
|
||||
*/
|
||||
@Override
|
||||
public void deleteTokenToIdMapping(String tokenValue) {
|
||||
// not action
|
||||
}
|
||||
/**
|
||||
* 更改 Token 指向的 账号Id 值
|
||||
*/
|
||||
@Override
|
||||
public void updateTokenToIdMapping(String tokenValue, Object loginId) {
|
||||
// not action
|
||||
}
|
||||
/**
|
||||
* 存储 Token-Id 映射
|
||||
*/
|
||||
@Override
|
||||
public void saveTokenToIdMapping(String tokenValue, Object loginId, long timeout) {
|
||||
// not action
|
||||
}
|
||||
|
||||
// ------------------- 过期时间相关 -------------------
|
||||
|
||||
/**
|
||||
* 获取当前登录者的 token 剩余有效时间 (单位: 秒)
|
||||
*/
|
||||
@Override
|
||||
public long getTokenTimeout() {
|
||||
return SaJwtUtil.getTimeout(getTokenValue(), loginType, jwtSecretKey());
|
||||
}
|
||||
|
||||
|
||||
// ------------------- 会话管理 -------------------
|
||||
|
||||
/**
|
||||
* [禁用] 根据条件查询Token
|
||||
*/
|
||||
@Override
|
||||
public List<String> searchTokenValue(String keyword, int start, int size) {
|
||||
throw new ApiDisabledException();
|
||||
}
|
||||
|
||||
|
||||
// ------------------- Bean对象代理 -------------------
|
||||
|
||||
/**
|
||||
* 返回全局配置对象的isShare属性
|
||||
* @return /
|
||||
*/
|
||||
@Override
|
||||
public boolean getConfigOfIsShare() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package cn.dev33.satoken.jwt;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import cn.dev33.satoken.exception.SaTokenException;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
|
||||
/**
|
||||
* Sa-Token 整合 jwt -- Simple 简单模式
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class StpLogicJwtForSimple extends StpLogic {
|
||||
|
||||
/**
|
||||
* Sa-Token 整合 jwt -- Simple模式
|
||||
*/
|
||||
public StpLogicJwtForSimple() {
|
||||
super(StpUtil.TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sa-Token 整合 jwt -- Simple模式
|
||||
* @param loginType 账号体系标识
|
||||
*/
|
||||
public StpLogicJwtForSimple(String loginType) {
|
||||
super(loginType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取jwt秘钥
|
||||
* @return /
|
||||
*/
|
||||
public String jwtSecretKey() {
|
||||
String keyt = getConfig().getJwtSecretKey();
|
||||
SaTokenException.throwByNull(keyt, "请配置jwt秘钥");
|
||||
return keyt;
|
||||
}
|
||||
|
||||
// ------ 重写方法
|
||||
|
||||
/**
|
||||
* 创建一个TokenValue
|
||||
*/
|
||||
@Override
|
||||
public String createTokenValue(Object loginId, String device, long timeout, Map<String, Object> extraData) {
|
||||
return SaJwtUtil.createToken(loginType, loginId, extraData, jwtSecretKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Token携带的扩展信息
|
||||
*/
|
||||
@Override
|
||||
public Object getExtra(String key) {
|
||||
return SaJwtUtil.getPayloadsNotCheck(getTokenValue(), loginType, jwtSecretKey()).get(key);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,34 +1,35 @@
|
||||
package cn.dev33.satoken.jwt;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import cn.dev33.satoken.dao.SaTokenDao;
|
||||
import cn.dev33.satoken.exception.ApiDisabledException;
|
||||
import cn.dev33.satoken.exception.NotLoginException;
|
||||
import cn.dev33.satoken.exception.SaTokenException;
|
||||
import cn.dev33.satoken.jwt.exception.SaJwtException;
|
||||
import cn.dev33.satoken.stp.SaLoginModel;
|
||||
import cn.dev33.satoken.stp.SaTokenInfo;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
|
||||
import java.util.Map;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
|
||||
/**
|
||||
* Sa-Token 整合 jwt -- stateless 无状态
|
||||
* Sa-Token 整合 jwt -- Stateless 无状态模式
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class StpLogicJwtForStateless extends StpLogic {
|
||||
|
||||
/**
|
||||
* Sa-Token 整合 jwt -- stateless 无状态
|
||||
* Sa-Token 整合 jwt -- Stateless 无状态
|
||||
*/
|
||||
public StpLogicJwtForStateless() {
|
||||
super(StpUtil.TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sa-Token 整合 jwt -- stateless 无状态
|
||||
* Sa-Token 整合 jwt -- Stateless 无状态
|
||||
* @param loginType 账号体系标识
|
||||
*/
|
||||
public StpLogicJwtForStateless(String loginType) {
|
||||
@@ -108,16 +109,10 @@ public class StpLogicJwtForStateless extends StpLogic {
|
||||
*/
|
||||
@Override
|
||||
public String getLoginIdNotHandle(String tokenValue) {
|
||||
// 先验证 loginType,如果不符,则视为无效token,返回null
|
||||
String loginType = SaJwtUtil.getPayloadsNotCheck(tokenValue, jwtSecretKey()).getStr(SaJwtUtil.LOGIN_TYPE);
|
||||
if(getLoginType().equals(loginType) == false) {
|
||||
return null;
|
||||
}
|
||||
// 获取 loginId
|
||||
try {
|
||||
Object loginId = SaJwtUtil.getLoginId(tokenValue, jwtSecretKey());
|
||||
Object loginId = SaJwtUtil.getLoginId(tokenValue, loginType, jwtSecretKey());
|
||||
return String.valueOf(loginId);
|
||||
} catch (NotLoginException e) {
|
||||
} catch (SaJwtException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -127,7 +122,11 @@ public class StpLogicJwtForStateless extends StpLogic {
|
||||
*/
|
||||
@Override
|
||||
public void logout() {
|
||||
// ...
|
||||
// 如果连token都没有,那么无需执行任何操作
|
||||
String tokenValue = getTokenValue();
|
||||
if(SaFoxUtil.isEmpty(tokenValue)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 从当前 [storage存储器] 里删除
|
||||
SaHolder.getStorage().delete(splicingKeyJustCreatedSave());
|
||||
@@ -143,7 +142,7 @@ public class StpLogicJwtForStateless extends StpLogic {
|
||||
*/
|
||||
@Override
|
||||
public Object getExtra(String key) {
|
||||
return SaJwtUtil.getPayloads(getTokenValue(), jwtSecretKey()).get(key);
|
||||
return SaJwtUtil.getPayloads(getTokenValue(), loginType, jwtSecretKey()).get(key);
|
||||
}
|
||||
|
||||
|
||||
@@ -154,7 +153,7 @@ public class StpLogicJwtForStateless extends StpLogic {
|
||||
*/
|
||||
@Override
|
||||
public long getTokenTimeout() {
|
||||
return SaJwtUtil.getTimeout(getTokenValue(), jwtSecretKey());
|
||||
return SaJwtUtil.getTimeout(getTokenValue(), loginType, jwtSecretKey());
|
||||
}
|
||||
|
||||
|
||||
@@ -176,7 +175,7 @@ public class StpLogicJwtForStateless extends StpLogic {
|
||||
return null;
|
||||
}
|
||||
// 获取
|
||||
return SaJwtUtil.getPayloadsNotCheck(tokenValue, jwtSecretKey()).getStr(SaJwtUtil.DEVICE);
|
||||
return SaJwtUtil.getPayloadsNotCheck(tokenValue, loginType, jwtSecretKey()).getStr(SaJwtUtil.DEVICE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,59 +1,12 @@
|
||||
package cn.dev33.satoken.jwt;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import cn.dev33.satoken.exception.SaTokenException;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
|
||||
/**
|
||||
* Sa-Token 整合 jwt -- Style模式
|
||||
* 已更名为 StpLogicJwtForSimple,请更换
|
||||
*
|
||||
* @author kong
|
||||
*
|
||||
* @date: 2022-5-1
|
||||
*/
|
||||
public class StpLogicJwtForStyle extends StpLogic {
|
||||
|
||||
/**
|
||||
* Sa-Token 整合 jwt -- Style模式
|
||||
*/
|
||||
public StpLogicJwtForStyle() {
|
||||
super(StpUtil.TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sa-Token 整合 jwt -- Style模式
|
||||
* @param loginType 账号体系标识
|
||||
*/
|
||||
public StpLogicJwtForStyle(String loginType) {
|
||||
super(loginType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取jwt秘钥
|
||||
* @return /
|
||||
*/
|
||||
public String jwtSecretKey() {
|
||||
String keyt = getConfig().getJwtSecretKey();
|
||||
SaTokenException.throwByNull(keyt, "请配置jwt秘钥");
|
||||
return keyt;
|
||||
}
|
||||
|
||||
// ------ 重写方法
|
||||
|
||||
/**
|
||||
* 创建一个TokenValue
|
||||
*/
|
||||
@Override
|
||||
public String createTokenValue(Object loginId, String device, long timeout, Map<String, Object> extraData) {
|
||||
return SaJwtUtil.createToken(loginId, extraData, jwtSecretKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Token携带的扩展信息
|
||||
*/
|
||||
@Override
|
||||
public Object getExtra(String key) {
|
||||
return SaJwtUtil.getPayloadsNotCheck(getTokenValue(), jwtSecretKey()).get(key);
|
||||
}
|
||||
@Deprecated
|
||||
public class StpLogicJwtForStyle extends StpLogicJwtForSimple {
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package cn.dev33.satoken.jwt.exception;
|
||||
|
||||
import cn.dev33.satoken.exception.SaTokenException;
|
||||
|
||||
|
||||
/**
|
||||
* 一个异常:代表 jwt 解析错误
|
||||
*
|
||||
* @author kong
|
||||
*/
|
||||
public class SaJwtException extends SaTokenException {
|
||||
|
||||
/**
|
||||
* 序列化版本号
|
||||
*/
|
||||
private static final long serialVersionUID = 6806129555290130114L;
|
||||
|
||||
/**
|
||||
* jwt 解析错误
|
||||
* @param message 异常描述
|
||||
*/
|
||||
public SaJwtException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* jwt 解析错误
|
||||
* @param message 异常描述
|
||||
* @param cause 异常对象
|
||||
*/
|
||||
public SaJwtException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入异常细分状态码
|
||||
* @param code 异常细分状态码
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaJwtException setCode(int code) {
|
||||
super.setCode(code);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果flag==true,则抛出message异常
|
||||
* @param flag 标记
|
||||
* @param message 异常信息
|
||||
*/
|
||||
public static void throwBy(boolean flag, String message) {
|
||||
if(flag) {
|
||||
throw new SaJwtException(message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package cn.dev33.satoken.jwt.exception;
|
||||
|
||||
/**
|
||||
* 定义所有 JWT 异常细分状态码
|
||||
*
|
||||
* @author kong
|
||||
* @date: 2022-5-1
|
||||
*/
|
||||
public class SaJwtExceptionCode {
|
||||
|
||||
/** 对 jwt 字符串解析失败 */
|
||||
public static final int CODE_40101 = 40101;
|
||||
|
||||
/** 此 jwt 的签名无效 */
|
||||
public static final int CODE_40102 = 40102;
|
||||
|
||||
/** 此 jwt 的 loginType 字段不符合预期 */
|
||||
public static final int CODE_40103 = 40103;
|
||||
|
||||
/** 此 jwt 已超时 */
|
||||
public static final int CODE_40104 = 40104;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user