Merge remote-tracking branch 'origin/master'

This commit is contained in:
liang.chao 2025-09-29 14:13:36 +08:00
commit 5c1b334028
1 changed files with 68 additions and 11 deletions

View File

@ -75,16 +75,23 @@ public class TokenService
String usernameFromJwt = (String) claims.get(Constants.JWT_USERNAME); String usernameFromJwt = (String) claims.get(Constants.JWT_USERNAME);
String userKey = getTokenKey(uuid); String userKey = getTokenKey(uuid);
LoginUser user = redisCache.getCacheObject(userKey); LoginUser user = redisCache.getCacheObject(userKey);
if (StringUtils.isNull(user)) if (StringUtils.isNull(user))
{ {
// login_tokens:{uuid} 已不存在视为会话被挤下线或已失效 // login_tokens:{uuid} 已不存在需要区分是过期还是被挤下线
// 为确保前端能提示其他设备登录在能解析出用户名时一律标记
if (StringUtils.isNotEmpty(usernameFromJwt)) if (StringUtils.isNotEmpty(usernameFromJwt))
{ {
request.setAttribute("forceLogoutByOtherDevice", Boolean.TRUE); String mappedUuid = redisCache.getCacheObject(getUserTokenKey(usernameFromJwt));
if (StringUtils.isNotEmpty(mappedUuid) && !uuid.equals(mappedUuid))
{
// 用户名映射存在且指向其他uuid说明是被其他设备挤下线
request.setAttribute("forceLogoutByOtherDevice", Boolean.TRUE);
}
// 否则就是正常的token过期不需要设置特殊标记
} }
return null; return null;
} }
// 单端在线校验username -> uuid 映射需要与当前token匹配 // 单端在线校验username -> uuid 映射需要与当前token匹配
String username = user.getUsername(); String username = user.getUsername();
String mappedUuid = redisCache.getCacheObject(getUserTokenKey(username)); String mappedUuid = redisCache.getCacheObject(getUserTokenKey(username));
@ -297,6 +304,9 @@ public class TokenService
return getToken(ServletUtils.getRequest()); return getToken(ServletUtils.getRequest());
} }
/**
* 根据token获取登录用户信息
*/
public LoginUser getLoginUser(String token){ public LoginUser getLoginUser(String token){
if (StringUtils.isNotEmpty(token)){ if (StringUtils.isNotEmpty(token)){
try try
@ -307,19 +317,23 @@ public class TokenService
String usernameFromJwt = (String) claims.get(Constants.JWT_USERNAME); String usernameFromJwt = (String) claims.get(Constants.JWT_USERNAME);
String userKey = getTokenKey(uuid); String userKey = getTokenKey(uuid);
LoginUser user = redisCache.getCacheObject(userKey); LoginUser user = redisCache.getCacheObject(userKey);
if (StringUtils.isNull(user)) if (StringUtils.isNull(user))
{ {
// 若login_tokens无此uuid检查用户名映射若映射存在且指向其他uuid则视为被其他设备挤下线 // 若login_tokens无此uuid检查用户名映射
if (StringUtils.isNotEmpty(usernameFromJwt)) if (StringUtils.isNotEmpty(usernameFromJwt))
{ {
String mappedUuid = redisCache.getCacheObject(getUserTokenKey(usernameFromJwt)); String mappedUuid = redisCache.getCacheObject(getUserTokenKey(usernameFromJwt));
if (StringUtils.isNotEmpty(mappedUuid) && !uuid.equals(mappedUuid)) if (StringUtils.isNotEmpty(mappedUuid) && !uuid.equals(mappedUuid))
{ {
// 被其他设备挤下线
return null; return null;
} }
// 否则是正常过期返回null
} }
return null; return null;
} }
String username = user.getUsername(); String username = user.getUsername();
String mappedUuid = redisCache.getCacheObject(getUserTokenKey(username)); String mappedUuid = redisCache.getCacheObject(getUserTokenKey(username));
if (StringUtils.isEmpty(mappedUuid) || !uuid.equals(mappedUuid)) if (StringUtils.isEmpty(mappedUuid) || !uuid.equals(mappedUuid))
@ -351,4 +365,47 @@ public class TokenService
} }
redisCache.setCacheObject(userTokenKey, uuid, expireTime, TimeUnit.MINUTES); redisCache.setCacheObject(userTokenKey, uuid, expireTime, TimeUnit.MINUTES);
} }
/**
* 检查token是否过期新增方法
*
* @param token token
* @return true-过期, false-未过期
*/
public boolean isTokenExpired(String token) {
try {
Claims claims = parseToken(token);
String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
String userKey = getTokenKey(uuid);
LoginUser user = redisCache.getCacheObject(userKey);
return StringUtils.isNull(user);
} catch (Exception e) {
log.error("检查token过期状态异常'{}'", e.getMessage());
return true;
}
}
/**
* 检查是否被其他设备挤下线新增方法
*
* @param token token
* @return true-被挤下线, false-未被挤下线
*/
public boolean isForceLogoutByOtherDevice(String token) {
try {
Claims claims = parseToken(token);
String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
String usernameFromJwt = (String) claims.get(Constants.JWT_USERNAME);
if (StringUtils.isNotEmpty(usernameFromJwt)) {
String mappedUuid = redisCache.getCacheObject(getUserTokenKey(usernameFromJwt));
// 如果用户名映射存在且指向其他uuid说明是被挤下线
return StringUtils.isNotEmpty(mappedUuid) && !uuid.equals(mappedUuid);
}
return false;
} catch (Exception e) {
log.error("检查是否被挤下线异常'{}'", e.getMessage());
return false;
}
}
} }