From 9283fa6e32145ff0ae237c40d2008fc35e81ef7c Mon Sep 17 00:00:00 2001
From: 无关风月 <443237572@qq.com>
Date: 星期一, 09 六月 2025 10:29:00 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev' into dev
---
ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java | 62 +++++++++++++++++++++++-------
1 files changed, 47 insertions(+), 15 deletions(-)
diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java
index ec3621d..65c95b0 100644
--- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java
+++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java
@@ -1,7 +1,9 @@
package com.ruoyi.common.security.service;
+import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.constant.SecurityConstants;
+import com.ruoyi.common.core.exception.GlobalException;
import com.ruoyi.common.core.utils.JwtUtils;
import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.common.core.utils.StringUtils;
@@ -19,6 +21,7 @@
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
@@ -110,9 +113,9 @@
claimsMap.put(SecurityConstants.DETAILS_USERNAME, userName);
// 接口返回信息
- Map<String, Object> rspMap = new HashMap<String, Object>();
+ Map<String, Object> rspMap = new HashMap<String, Object>(8);
rspMap.put("access_token", JwtUtils.createToken(claimsMap));
- rspMap.put("expires_in", expireTime);
+ rspMap.put("expires_in", CacheConstants.EXPIRE_TIME_WORKER);
return rspMap;
}
@@ -130,7 +133,7 @@
*
* @return 用户信息
*/
- public LoginUser getLoginUserByUser() {
+ public LoginUserInfo getLoginUserByUser() {
return getLoginUserByUser(ServletUtils.getRequest());
}
@@ -159,7 +162,7 @@
*
* @return 用户信息
*/
- public LoginUser getLoginUserByUser(HttpServletRequest request) {
+ public LoginUserInfo getLoginUserByUser(HttpServletRequest request) {
// 获取请求携带的令牌
String token = SecurityUtils.getToken(request);
return getLoginUserByUser(token);
@@ -200,8 +203,8 @@
*
* @return 用户信息
*/
- public LoginUser getLoginUserByUser(String token) {
- LoginUser user = null;
+ public LoginUserInfo getLoginUserByUser(String token) {
+ LoginUserInfo user = null;
try {
if (StringUtils.isNotEmpty(token)) {
String userkey = JwtUtils.getUserKeyByUser(token);
@@ -221,14 +224,25 @@
*/
public LoginUserInfo getLoginUserByWorker(String token) {
LoginUserInfo user = null;
- try {
- if (StringUtils.isNotEmpty(token)) {
- String userkey = JwtUtils.getUserKeyByWorker(token);
- user = redisService.getCacheObject(getTokenKeyByWorker(userkey));
- return user;
+ if (StringUtils.isNotEmpty(token)) {
+ String userkey = JwtUtils.getUserKeyByWorker(token);
+ String tokenKeyByWorker = getTokenKeyByWorker(userkey);
+ user = redisService.getCacheObject(getTokenKeyByWorker(userkey));
+ // 再次判断登录状态是否已过期
+ if (null == user) {
+ throw new GlobalException("登录信息已过期,请重新登录!", 504);
}
- } catch (Exception e) {
- log.error("获取用户信息异常'{}'", e.getMessage());
+ // 优先判断当前账号是否已在其他设备登录
+ if (!user.getIsCanLogin()) {
+ redisService.deleteObject(tokenKeyByWorker);
+ throw new GlobalException("当前登录账号在其他设备登录!", 505);
+ }
+ // 再次判断登录状态是否已过期
+ if (System.currentTimeMillis() > user.getExpireTime()) {
+ redisService.deleteObject(tokenKeyByWorker);
+ throw new GlobalException("登录信息已过期,请重新登录!", 504);
+ }
+ return user;
}
return user;
}
@@ -317,11 +331,29 @@
* @param loginUserInfo 登录信息
*/
public void refreshTokenByWorker(LoginUserInfo loginUserInfo) {
+ // 获取所有 login_tokens_study: 前缀的登录缓存
+ Set redisCache = redisService.getKeysPrefix(CacheConstants.LOGIN_WORKER_TOKEN_KEY);
+ for (Object key : redisCache) {
+ String strKey = String.valueOf(key);
+ // 根据 login_tokens:加密token 获取用户登录信息
+ Object redisCacheUserInfo = redisService.getCacheObject(strKey);
+ LoginUserInfo redisUserInfo = JSONObject.parseObject(JSONObject.toJSONString(redisCacheUserInfo), LoginUserInfo.class);
+ // 单点逻辑,如果当前用户已处于登录状态并再次登录,则清除该用户上一次登录token
+ if (loginUserInfo.getUserid().equals(redisUserInfo.getUserid())) {
+ // 被挤账户 可登录状态 已经为 false时,跳出循环
+ if (!redisUserInfo.getIsCanLogin()) {
+ continue;
+ }
+ // 设置能否登录字段为 否,当该token登录时,isCanLogin为false表示账号被挤
+ redisUserInfo.setIsCanLogin(Boolean.FALSE);
+ redisService.setCacheObject(strKey, redisUserInfo, redisService.getExpire(strKey), TimeUnit.SECONDS);
+ }
+ }
loginUserInfo.setLoginTime(System.currentTimeMillis());
- loginUserInfo.setExpireTime(loginUserInfo.getLoginTime() + expireTime * MILLIS_MINUTE);
+ loginUserInfo.setExpireTime(loginUserInfo.getLoginTime() + CacheConstants.EXPIRE_TIME_WORKER * MILLIS_MINUTE);
// 根据uuid将loginUser缓存
String userKey = getTokenKeyByWorker(loginUserInfo.getToken());
- redisService.setCacheObject(userKey, loginUserInfo, expireTime, TimeUnit.MINUTES);
+ redisService.setCacheObject(userKey, loginUserInfo, CacheConstants.EXPIRE_TIME_WORKER, TimeUnit.MINUTES);
}
private String getTokenKey(String token) {
--
Gitblit v1.7.1