update satoken 1.40.0 => 1.42.0 适配所有升级项(改动较多)

SaLoginModel -> SaLoginParameter
device -> deviceType
satoken BCrypt -> hutool BCrypt(satoken不维护了)
SaTokenDao -> SaTokenDaoBySessionFollowObject(satoken做了重构封装)
sse 适配新satoken版本拦截器变化
This commit is contained in:
疯狂的狮子Li 2025-04-11 15:36:38 +08:00
parent 538aa8d908
commit 31502dccc7
16 changed files with 69 additions and 49 deletions

View File

@ -23,7 +23,7 @@
<therapi-javadoc.version>0.15.0</therapi-javadoc.version>
<easyexcel.version>4.0.3</easyexcel.version>
<velocity.version>2.3</velocity.version>
<satoken.version>1.40.0</satoken.version>
<satoken.version>1.42.0</satoken.version>
<mybatis-plus.version>3.5.11</mybatis-plus.version>
<p6spy.version>3.9.1</p6spy.version>
<hutool.version>5.8.35</hutool.version>

View File

@ -1,8 +1,8 @@
package org.dromara.web.listener;
import cn.dev33.satoken.listener.SaTokenListener;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.hutool.core.convert.Convert;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
@ -40,7 +40,7 @@ public class UserActionListener implements SaTokenListener {
* 每次登录时触发
*/
@Override
public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) {
public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginParameter loginParameter) {
UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent"));
String ip = ServletUtils.getClientIP();
UserOnlineDTO dto = new UserOnlineDTO();
@ -50,17 +50,17 @@ public class UserActionListener implements SaTokenListener {
dto.setOs(userAgent.getOs().getName());
dto.setLoginTime(System.currentTimeMillis());
dto.setTokenId(tokenValue);
String username = (String) loginModel.getExtra(LoginHelper.USER_NAME_KEY);
String tenantId = (String) loginModel.getExtra(LoginHelper.TENANT_KEY);
String username = (String) loginParameter.getExtra(LoginHelper.USER_NAME_KEY);
String tenantId = (String) loginParameter.getExtra(LoginHelper.TENANT_KEY);
dto.setUserName(username);
dto.setClientKey((String) loginModel.getExtra(LoginHelper.CLIENT_KEY));
dto.setDeviceType(loginModel.getDevice());
dto.setDeptName((String) loginModel.getExtra(LoginHelper.DEPT_NAME_KEY));
dto.setClientKey((String) loginParameter.getExtra(LoginHelper.CLIENT_KEY));
dto.setDeviceType(loginParameter.getDeviceType());
dto.setDeptName((String) loginParameter.getExtra(LoginHelper.DEPT_NAME_KEY));
TenantHelper.dynamic(tenantId, () -> {
if(loginModel.getTimeout() == -1) {
if(loginParameter.getTimeout() == -1) {
RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto);
} else {
RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto, Duration.ofSeconds(loginModel.getTimeout()));
RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto, Duration.ofSeconds(loginParameter.getTimeout()));
}
});
// 记录登录日志
@ -72,7 +72,7 @@ public class UserActionListener implements SaTokenListener {
logininforEvent.setRequest(ServletUtils.getRequest());
SpringUtils.context().publishEvent(logininforEvent);
// 更新登录信息
loginService.recordLoginInfo((Long) loginModel.getExtra(LoginHelper.USER_KEY), ip);
loginService.recordLoginInfo((Long) loginParameter.getExtra(LoginHelper.USER_KEY), ip);
log.info("user doLogin, userId:{}, token:{}", loginId, tokenValue);
}

View File

@ -1,6 +1,6 @@
package org.dromara.web.service;
import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.constant.Constants;

View File

@ -1,7 +1,7 @@
package org.dromara.web.service.impl;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
@ -58,8 +58,8 @@ public class EmailAuthStrategy implements IAuthStrategy {
});
loginUser.setClientKey(client.getClientKey());
loginUser.setDeviceType(client.getDeviceType());
SaLoginModel model = new SaLoginModel();
model.setDevice(client.getDeviceType());
SaLoginParameter model = new SaLoginParameter();
model.setDeviceType(client.getDeviceType());
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
// 例如: 后台用户30分钟过期 app用户1天过期
model.setTimeout(client.getTimeout());

View File

@ -1,9 +1,9 @@
package org.dromara.web.service.impl;
import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -70,8 +70,8 @@ public class PasswordAuthStrategy implements IAuthStrategy {
});
loginUser.setClientKey(client.getClientKey());
loginUser.setDeviceType(client.getDeviceType());
SaLoginModel model = new SaLoginModel();
model.setDevice(client.getDeviceType());
SaLoginParameter model = new SaLoginParameter();
model.setDeviceType(client.getDeviceType());
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
// 例如: 后台用户30分钟过期 app用户1天过期
model.setTimeout(client.getTimeout());

View File

@ -1,7 +1,7 @@
package org.dromara.web.service.impl;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
@ -58,8 +58,8 @@ public class SmsAuthStrategy implements IAuthStrategy {
});
loginUser.setClientKey(client.getClientKey());
loginUser.setDeviceType(client.getDeviceType());
SaLoginModel model = new SaLoginModel();
model.setDevice(client.getDeviceType());
SaLoginParameter model = new SaLoginParameter();
model.setDeviceType(client.getDeviceType());
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
// 例如: 后台用户30分钟过期 app用户1天过期
model.setTimeout(client.getTimeout());

View File

@ -1,7 +1,7 @@
package org.dromara.web.service.impl;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
@ -99,8 +99,8 @@ public class SocialAuthStrategy implements IAuthStrategy {
});
loginUser.setClientKey(client.getClientKey());
loginUser.setDeviceType(client.getDeviceType());
SaLoginModel model = new SaLoginModel();
model.setDevice(client.getDeviceType());
SaLoginParameter model = new SaLoginParameter();
model.setDeviceType(client.getDeviceType());
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
// 例如: 后台用户30分钟过期 app用户1天过期
model.setTimeout(client.getTimeout());

View File

@ -1,7 +1,7 @@
package org.dromara.web.service.impl;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -76,8 +76,8 @@ public class XcxAuthStrategy implements IAuthStrategy {
loginUser.setDeviceType(client.getDeviceType());
loginUser.setOpenid(openid);
SaLoginModel model = new SaLoginModel();
model.setDevice(client.getDeviceType());
SaLoginParameter model = new SaLoginParameter();
model.setDeviceType(client.getDeviceType());
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
// 例如: 后台用户30分钟过期 app用户1天过期
model.setTimeout(client.getTimeout());

View File

@ -1,6 +1,6 @@
package org.dromara.common.satoken.core.dao;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.dao.auto.SaTokenDaoBySessionFollowObject;
import cn.dev33.satoken.util.SaFoxUtil;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
@ -16,10 +16,12 @@ import java.util.concurrent.TimeUnit;
* Sa-Token持久层接口(使用框架自带RedisUtils实现 协议统一)
* <p>
* 采用 caffeine + redis 多级缓存 优化并发查询效率
* <p>
* SaTokenDaoBySessionFollowObject SaTokenDao 子集简化了session方法处理
*
* @author Lion Li
*/
public class PlusSaTokenDao implements SaTokenDao {
public class PlusSaTokenDao implements SaTokenDaoBySessionFollowObject {
private static final Cache<String, Object> CAFFEINE = Caffeine.newBuilder()
// 设置最后一次写入或访问后经过固定时间过期
@ -107,6 +109,19 @@ public class PlusSaTokenDao implements SaTokenDao {
return o;
}
/**
* 获取 Object (指定反序列化类型)如无返空
*
* @param key 键名称
* @return object
*/
@SuppressWarnings("unchecked cast")
@Override
public <T> T getObject(String key, Class<T> classType) {
Object o = CAFFEINE.get(key, k -> RedisUtils.getCacheObject(key));
return (T) o;
}
/**
* 写入Object并设定存活时间 (单位: )
*/
@ -165,7 +180,6 @@ public class PlusSaTokenDao implements SaTokenDao {
RedisUtils.expire(key, Duration.ofSeconds(timeout));
}
/**
* 搜索数据
*/

View File

@ -1,8 +1,8 @@
package org.dromara.common.satoken.utils;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
@ -47,8 +47,8 @@ public class LoginHelper {
* @param loginUser 登录用户信息
* @param model 配置参数
*/
public static void login(LoginUser loginUser, SaLoginModel model) {
model = ObjectUtil.defaultIfNull(model, new SaLoginModel());
public static void login(LoginUser loginUser, SaLoginParameter model) {
model = ObjectUtil.defaultIfNull(model, new SaLoginParameter());
StpUtil.login(loginUser.getLoginId(),
model.setExtra(TENANT_KEY, loginUser.getTenantId())
.setExtra(USER_KEY, loginUser.getUserId())

View File

@ -11,13 +11,13 @@ import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.SseException;
import org.dromara.common.core.utils.ServletUtils;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.security.config.properties.SecurityProperties;
import org.dromara.common.security.handler.AllUrlHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
@ -37,6 +37,8 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
public class SecurityConfig implements WebMvcConfigurer {
private final SecurityProperties securityProperties;
@Value("${sse.path}")
private String ssePath;
/**
* 注册sa-token的拦截器
@ -54,15 +56,7 @@ public class SecurityConfig implements WebMvcConfigurer {
.check(() -> {
HttpServletRequest request = ServletUtils.getRequest();
// 检查是否登录 是否有token
try {
StpUtil.checkLogin();
} catch (NotLoginException e) {
if (request.getRequestURI().contains("sse")) {
throw new SseException(e.getMessage(), e.getCode());
} else {
throw e;
}
}
StpUtil.checkLogin();
// 检查 header param 里的 clientid token 里的是否一致
String headerCid = request.getHeader(LoginHelper.CLIENT_KEY);
@ -84,7 +78,8 @@ public class SecurityConfig implements WebMvcConfigurer {
});
})).addPathPatterns("/**")
// 排除不需要拦截的路径
.excludePathPatterns(securityProperties.getExcludes());
.excludePathPatterns(securityProperties.getExcludes())
.excludePathPatterns(ssePath);
}
/**

View File

@ -33,6 +33,7 @@ public class SseController implements DisposableBean {
*/
@GetMapping(value = "${sse.path}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter connect() {
StpUtil.checkLogin();
String tokenValue = StpUtil.getTokenValue();
Long userId = LoginHelper.getUserId();
return sseEmitterManager.connect(userId, tokenValue);

View File

@ -81,6 +81,17 @@ public class TenantSaTokenDao extends PlusSaTokenDao {
return super.getObject(GlobalConstants.GLOBAL_REDIS_KEY + key);
}
/**
* 获取 Object (指定反序列化类型)如无返空
*
* @param key 键名称
* @return object
*/
@Override
public <T> T getObject(String key, Class<T> classType) {
return super.getObject(GlobalConstants.GLOBAL_REDIS_KEY + key, classType);
}
/**
* 写入Object并设定存活时间 (单位: )
*/
@ -137,7 +148,6 @@ public class TenantSaTokenDao extends PlusSaTokenDao {
RedisUtils.expire(GlobalConstants.GLOBAL_REDIS_KEY + key, Duration.ofSeconds(timeout));
}
/**
* 搜索数据
*/

View File

@ -1,8 +1,8 @@
package org.dromara.system.controller.system;
import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.crypto.digest.BCrypt;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.StringUtils;

View File

@ -1,10 +1,10 @@
package org.dromara.system.controller.system;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.digest.BCrypt;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;

View File

@ -1,11 +1,11 @@
package org.dromara.system.service.impl;
import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;