Merge remote-tracking branch 'origin/dev-ltx' into dev/3.1_release_merge
This commit is contained in:
@@ -6,6 +6,7 @@ import com.ai.da.common.context.UserContext;
|
||||
import com.ai.da.common.security.config.SecurityProperties;
|
||||
import com.ai.da.common.security.jwt.JWTTokenHelper;
|
||||
import com.ai.da.common.utils.LocalCacheUtils;
|
||||
import com.ai.da.common.utils.RedisUtil;
|
||||
import com.ai.da.common.utils.MultiReadHttpServletRequest;
|
||||
import com.ai.da.common.utils.MultiReadHttpServletResponse;
|
||||
import com.ai.da.common.utils.RequestInfoUtil;
|
||||
@@ -40,6 +41,8 @@ public class AuthenticationFilter extends OncePerRequestFilter {
|
||||
private JWTTokenHelper jwtTokenHelper;
|
||||
@Resource
|
||||
private SecurityProperties properties;
|
||||
@Resource
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
private static final List<String> FILTER_URL =
|
||||
Arrays.asList("/favicon.ico", "/doc.html", "/swagger-ui.html",
|
||||
@@ -132,12 +135,19 @@ public class AuthenticationFilter extends OncePerRequestFilter {
|
||||
UserContext.delete();
|
||||
//存取用户信息到缓存
|
||||
UserContext.setUserHolder(principal);
|
||||
//校验token
|
||||
String cacheToken = LocalCacheUtils.getTokenCache(String.valueOf(principal.getId()));
|
||||
// 校验 token:先查本地缓存,再查 Redis,保证服务重启后仍然有效
|
||||
String userIdStr = String.valueOf(principal.getId());
|
||||
String cacheToken = LocalCacheUtils.getTokenCache(userIdStr);
|
||||
|
||||
if(StringUtils.isEmpty(cacheToken)){
|
||||
// throw new RuntimeException("TOKEN已过期,请重新登录!");
|
||||
throw new TokenMissingOrExpiredException("TOKEN已过期,请重新登录!(local cache empty)");
|
||||
if (StringUtils.isEmpty(cacheToken)) {
|
||||
// 本地缓存为空时,尝试从 Redis 读取
|
||||
cacheToken = redisUtil.getLoginToken(principal.getId());
|
||||
if (StringUtils.isEmpty(cacheToken)) {
|
||||
// throw new RuntimeException("TOKEN已过期,请重新登录!");
|
||||
throw new TokenMissingOrExpiredException("TOKEN已过期,请重新登录!(cache & redis empty)");
|
||||
}
|
||||
// 将 Redis 中的 token 回填到本地缓存,减少后续 Redis 访问
|
||||
LocalCacheUtils.setTokenCache(userIdStr, cacheToken);
|
||||
}
|
||||
if(!cacheToken.equals(jwtToken) ){
|
||||
// throw new RuntimeException("TOKEN已过期,请重新登录!");
|
||||
|
||||
@@ -34,6 +34,11 @@ public class RedisUtil {
|
||||
private RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
public final static String FLUX_POLLING_URL = "Flux:";
|
||||
/**
|
||||
* 登录 token 在 Redis 中的前缀:
|
||||
* 最终 key 结构为 login:token:{userId}
|
||||
*/
|
||||
public final static String LOGIN_TOKEN_KEY = "login:token:";
|
||||
|
||||
public Boolean hasKey(String key){
|
||||
return redisTemplate.hasKey(key);
|
||||
@@ -186,6 +191,40 @@ public class RedisUtil {
|
||||
redisTemplate.delete(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存登录 token
|
||||
*
|
||||
* @param userId 用户 ID
|
||||
* @param token token 字符串
|
||||
* @param expireMillis 过期时间(毫秒,通常与 JWT 保持一致)
|
||||
*/
|
||||
public void setLoginToken(Long userId, String token, long expireMillis) {
|
||||
if (expireMillis <= 0) {
|
||||
// 不设置过期时间,直到手动删除(不推荐)
|
||||
addToString(LOGIN_TOKEN_KEY + userId, token);
|
||||
return;
|
||||
}
|
||||
long expireSeconds = expireMillis / 1000;
|
||||
if (expireSeconds <= 0) {
|
||||
expireSeconds = 1;
|
||||
}
|
||||
addToString(LOGIN_TOKEN_KEY + userId, token, expireSeconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录 token
|
||||
*/
|
||||
public String getLoginToken(Long userId) {
|
||||
return getFromString(LOGIN_TOKEN_KEY + userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除登录 token
|
||||
*/
|
||||
public void deleteLoginToken(Long userId) {
|
||||
removeFromString(LOGIN_TOKEN_KEY + userId);
|
||||
}
|
||||
|
||||
public final static String PORTFOLIO_LIKE_KEY = "portfolio:like:";
|
||||
|
||||
public void likePost(Long portfolioId, Long userId) {
|
||||
|
||||
@@ -132,6 +132,9 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
@Resource
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
@Resource
|
||||
private com.ai.da.common.security.config.SecurityProperties securityProperties;
|
||||
|
||||
@Resource
|
||||
private UserFollowService userFollowService;
|
||||
|
||||
@@ -344,7 +347,11 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
principal.setLanguage(account.getLanguage());
|
||||
principal.setCountry(account.getCountry());
|
||||
String token2 = jwtTokenHelper.createToken(principal);
|
||||
// 本地 JVM 缓存(适配旧逻辑)
|
||||
LocalCacheUtils.setTokenCache(String.valueOf(account.getId()), token2);
|
||||
// 同步写入 Redis,重启后仍然可用
|
||||
long jwtExpiration = securityProperties.getJwtExpiration();
|
||||
redisUtil.setLoginToken(account.getId(), token2, jwtExpiration);
|
||||
return token2;
|
||||
}
|
||||
|
||||
@@ -600,21 +607,25 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
|
||||
@Override
|
||||
public Boolean logout(AccountLogoutDTO accountLogoutDTO) {
|
||||
//jwt本身失效比较难做 统一用缓存实现 删除缓存就失效
|
||||
String token = LocalCacheUtils.getTokenCache(String.valueOf(accountLogoutDTO.getUserId()));
|
||||
if (StringUtils.isNotBlank(token)) {
|
||||
LocalCacheUtils.delTokenCache(String.valueOf(accountLogoutDTO.getUserId()));
|
||||
}
|
||||
// jwt 本身失效比较难做,统一用缓存实现:删除缓存即失效
|
||||
String userIdStr = String.valueOf(accountLogoutDTO.getUserId());
|
||||
LocalCacheUtils.delTokenCache(userIdStr);
|
||||
// 同时删除 Redis 中的 token,防止服务重启后仍然有效
|
||||
redisUtil.deleteLoginToken(accountLogoutDTO.getUserId());
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean isLogin(AccountLogoutDTO accountLogoutDTO) {
|
||||
String token = LocalCacheUtils.getTokenCache(String.valueOf(accountLogoutDTO.getUserId()));
|
||||
String userIdStr = String.valueOf(accountLogoutDTO.getUserId());
|
||||
// 先查本地缓存
|
||||
String token = LocalCacheUtils.getTokenCache(userIdStr);
|
||||
if (StringUtils.isNotBlank(token)) {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
return Boolean.FALSE;
|
||||
// 本地没有时,再查 Redis,保证服务重启后也能判断登录状态
|
||||
String redisToken = redisUtil.getLoginToken(accountLogoutDTO.getUserId());
|
||||
return StringUtils.isNotBlank(redisToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -812,6 +823,8 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
if (StringUtils.isNotBlank(token)) {
|
||||
LocalCacheUtils.delTokenCache(String.valueOf(accountDelete.getId()));
|
||||
}
|
||||
// 删除 Redis 中对应的登录 token
|
||||
redisUtil.deleteLoginToken(accountDelete.getId());
|
||||
if (!userName.equals(userToBeUpdate.getUserName())) {
|
||||
// accountMapper.deleteById(accountDelete);
|
||||
log.info("排查用户被删除原因:deleteNoLoginRequired,true, 删除用户(改为降为游客)");
|
||||
@@ -1065,6 +1078,8 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
if (StringUtils.isNotBlank(token)) {
|
||||
LocalCacheUtils.delTokenCache(String.valueOf(account.getId()));
|
||||
}
|
||||
// 删除 Redis 中对应的登录 token
|
||||
redisUtil.deleteLoginToken(account.getId());
|
||||
// accountMapper.deleteById(account.getId());
|
||||
log.info("排查用户被删除原因:deleteNoLoginRequiredNew,删除用户(改为降为游客)");
|
||||
accountMapper.toVisitor(account.getId());
|
||||
|
||||
Reference in New Issue
Block a user