From 9e4b697c0324ee533fb0a23cba1266b97038d58e Mon Sep 17 00:00:00 2001 From: lizhengwei Date: Tue, 7 Apr 2026 14:43:08 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A7=BB=E9=99=A4=20CacheConstants.ONLINE=5FTO?= =?UTF-8?q?KEN=5FKEY=20=E8=AE=B0=E5=BD=95=E5=9C=A8=E7=BA=BF=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E7=9A=84=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/core/constant/CacheConstants.java | 5 +++ .../monitor/SysSaasUserOnlineController.java | 11 ++++-- .../monitor/SysUserOnlineController.java | 11 ++++-- .../web/listener/UserActionListener.java | 35 +++--------------- .../handler/GatewayExceptionHandler.java | 2 +- .../sso/listener/UserActionListener.java | 37 +++---------------- 6 files changed, 34 insertions(+), 67 deletions(-) diff --git a/ruoyi-common/ruoyi-common-core-api/src/main/java/org/dromara/common/core/constant/CacheConstants.java b/ruoyi-common/ruoyi-common-core-api/src/main/java/org/dromara/common/core/constant/CacheConstants.java index ceb837044..54ebc3dc0 100644 --- a/ruoyi-common/ruoyi-common-core-api/src/main/java/org/dromara/common/core/constant/CacheConstants.java +++ b/ruoyi-common/ruoyi-common-core-api/src/main/java/org/dromara/common/core/constant/CacheConstants.java @@ -12,6 +12,11 @@ public interface CacheConstants { */ String ONLINE_TOKEN_KEY = "online_tokens:"; + /** + * 在线用户 satoken redis key + */ + String UserOnline = "UserOnline"; + /** * 参数管理 cache key */ diff --git a/ruoyi-modules/ruoyi-md-system-saas/ruoyi-md-system-saas-service/src/main/java/org/dromara/system/saas/controller/monitor/SysSaasUserOnlineController.java b/ruoyi-modules/ruoyi-md-system-saas/ruoyi-md-system-saas-service/src/main/java/org/dromara/system/saas/controller/monitor/SysSaasUserOnlineController.java index c14a36ec4..79300b13c 100644 --- a/ruoyi-modules/ruoyi-md-system-saas/ruoyi-md-system-saas-service/src/main/java/org/dromara/system/saas/controller/monitor/SysSaasUserOnlineController.java +++ b/ruoyi-modules/ruoyi-md-system-saas/ruoyi-md-system-saas-service/src/main/java/org/dromara/system/saas/controller/monitor/SysSaasUserOnlineController.java @@ -13,7 +13,6 @@ import org.dromara.common.core.utils.StringUtils; import org.dromara.common.log.annotation.Log; import org.dromara.common.log.enums.BusinessType; import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.redis.utils.RedisUtils; import org.dromara.common.web.core.BaseController; import org.dromara.system.saas.domain.SysSaasUserOnline; import org.springframework.web.bind.annotation.*; @@ -21,6 +20,7 @@ import org.springframework.web.bind.annotation.*; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; /** @@ -51,7 +51,11 @@ public class SysSaasUserOnlineController extends BaseController { if (StpUtil.stpLogic.getTokenActiveTimeoutByToken(token) < -1) { continue; } - userOnlineDTOList.add(RedisUtils.getCacheObject(CacheConstants.ONLINE_TOKEN_KEY + token)); + // 从SaToken的会话中获取用户信息对象 + UserOnlineDTO dto = (UserOnlineDTO) StpUtil.stpLogic.getTokenSessionByToken(token).get(CacheConstants.UserOnline); + if (dto != null) { + userOnlineDTOList.add(dto); + } } if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) { userOnlineDTOList = StreamUtils.filter(userOnlineDTOList, userOnline -> @@ -98,7 +102,8 @@ public class SysSaasUserOnlineController extends BaseController { List tokenIds = StpUtil.getTokenValueListByLoginId(StpUtil.getLoginIdAsString()); List userOnlineDTOList = tokenIds.stream() .filter(token -> StpUtil.stpLogic.getTokenActiveTimeoutByToken(token) >= -1) - .map(token -> (UserOnlineDTO) RedisUtils.getCacheObject(CacheConstants.ONLINE_TOKEN_KEY + token)) + .map(token -> (UserOnlineDTO) StpUtil.stpLogic.getTokenSessionByToken(token).get(CacheConstants.UserOnline)) + .filter(Objects::nonNull) .collect(Collectors.toList()); //复制和处理 SysSaasUserOnline 对象列表 Collections.reverse(userOnlineDTOList); diff --git a/ruoyi-modules/ruoyi-md-system/ruoyi-md-system-service/src/main/java/org/dromara/system/controller/monitor/SysUserOnlineController.java b/ruoyi-modules/ruoyi-md-system/ruoyi-md-system-service/src/main/java/org/dromara/system/controller/monitor/SysUserOnlineController.java index 9b08c2d2c..b9b0c3f6f 100644 --- a/ruoyi-modules/ruoyi-md-system/ruoyi-md-system-service/src/main/java/org/dromara/system/controller/monitor/SysUserOnlineController.java +++ b/ruoyi-modules/ruoyi-md-system/ruoyi-md-system-service/src/main/java/org/dromara/system/controller/monitor/SysUserOnlineController.java @@ -13,7 +13,6 @@ import org.dromara.common.core.utils.StringUtils; import org.dromara.common.log.annotation.Log; import org.dromara.common.log.enums.BusinessType; import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.redis.utils.RedisUtils; import org.dromara.common.web.core.BaseController; import org.dromara.system.domain.SysUserOnline; import org.springframework.web.bind.annotation.*; @@ -21,6 +20,7 @@ import org.springframework.web.bind.annotation.*; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; /** @@ -51,7 +51,11 @@ public class SysUserOnlineController extends BaseController { if (StpUtil.stpLogic.getTokenActiveTimeoutByToken(token) < -1) { continue; } - userOnlineDTOList.add(RedisUtils.getCacheObject(CacheConstants.ONLINE_TOKEN_KEY + token)); + // 从SaToken的会话中获取用户信息对象 + UserOnlineDTO dto = (UserOnlineDTO) StpUtil.stpLogic.getTokenSessionByToken(token).get(CacheConstants.UserOnline); + if (dto != null) { + userOnlineDTOList.add(dto); + } } if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) { userOnlineDTOList = StreamUtils.filter(userOnlineDTOList, userOnline -> @@ -98,7 +102,8 @@ public class SysUserOnlineController extends BaseController { List tokenIds = StpUtil.getTokenValueListByLoginId(StpUtil.getLoginIdAsString()); List userOnlineDTOList = tokenIds.stream() .filter(token -> StpUtil.stpLogic.getTokenActiveTimeoutByToken(token) >= -1) - .map(token -> (UserOnlineDTO) RedisUtils.getCacheObject(CacheConstants.ONLINE_TOKEN_KEY + token)) + .map(token -> (UserOnlineDTO) StpUtil.stpLogic.getTokenSessionByToken(token).get(CacheConstants.UserOnline)) + .filter(Objects::nonNull) .collect(Collectors.toList()); //复制和处理 SysUserOnline 对象列表 Collections.reverse(userOnlineDTOList); diff --git a/ruoyi-site/ruoyi-admin/src/main/java/org/dromara/web/listener/UserActionListener.java b/ruoyi-site/ruoyi-admin/src/main/java/org/dromara/web/listener/UserActionListener.java index 07595e092..3a5f70ea0 100644 --- a/ruoyi-site/ruoyi-admin/src/main/java/org/dromara/web/listener/UserActionListener.java +++ b/ruoyi-site/ruoyi-admin/src/main/java/org/dromara/web/listener/UserActionListener.java @@ -1,10 +1,8 @@ package org.dromara.web.listener; -import cn.dev33.satoken.config.SaTokenConfig; import cn.dev33.satoken.listener.SaTokenListener; import cn.dev33.satoken.stp.SaLoginModel; import cn.dev33.satoken.stp.StpUtil; -import cn.hutool.core.convert.Convert; import cn.hutool.http.useragent.UserAgent; import cn.hutool.http.useragent.UserAgentUtil; import lombok.RequiredArgsConstructor; @@ -17,16 +15,12 @@ import org.dromara.common.core.utils.ServletUtils; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.ip.AddressUtils; import org.dromara.common.log.event.LogininforEvent; -import org.dromara.common.redis.utils.RedisUtils; import org.dromara.common.satoken.utils.LoginHelper; -import org.dromara.common.tenant.helper.TenantHelper; import org.dromara.web.service.SysLoginService; import org.springframework.stereotype.Component; -import java.time.Duration; - /** - * 用户行为 侦听器的实现 + * 租户管理平台 用户行为 侦听器的实现 * * @author Lion Li */ @@ -35,7 +29,6 @@ import java.time.Duration; @Slf4j public class UserActionListener implements SaTokenListener { - private final SaTokenConfig tokenConfig; private final SysLoginService loginService; /** @@ -45,6 +38,9 @@ public class UserActionListener implements SaTokenListener { public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) { UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent")); String ip = ServletUtils.getClientIP(); + String username = (String) loginModel.getExtra(LoginHelper.USER_NAME_KEY); + String tenantId = (String) loginModel.getExtra(LoginHelper.TENANT_KEY); + // 将用户信息作为对象存储到SaToken的会话中 UserOnlineDTO dto = new UserOnlineDTO(); dto.setIpaddr(ip); dto.setLoginLocation(AddressUtils.getRealAddressByIP(ip)); @@ -52,19 +48,12 @@ 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); dto.setUserName(username); dto.setClientKey((String) loginModel.getExtra(LoginHelper.CLIENT_KEY)); dto.setDeviceType(loginModel.getDevice()); dto.setDeptName((String) loginModel.getExtra(LoginHelper.DEPT_NAME_KEY)); - TenantHelper.dynamic(tenantId, () -> { - if(tokenConfig.getTimeout() == -1) { - RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto); - } else { - RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto, Duration.ofSeconds(tokenConfig.getTimeout())); - } - }); + // 使用会话存储用户信息 + StpUtil.stpLogic.getTokenSessionByToken(tokenValue).set(CacheConstants.UserOnline, dto); // 记录登录日志 LogininforEvent logininforEvent = new LogininforEvent(); logininforEvent.setTenantId(tenantId); @@ -83,10 +72,6 @@ public class UserActionListener implements SaTokenListener { */ @Override public void doLogout(String loginType, Object loginId, String tokenValue) { - String tenantId = Convert.toStr(StpUtil.getExtra(tokenValue, LoginHelper.TENANT_KEY)); - TenantHelper.dynamic(tenantId, () -> { - RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); - }); log.info("user doLogout, userId:{}, token:{}", loginId, tokenValue); } @@ -95,10 +80,6 @@ public class UserActionListener implements SaTokenListener { */ @Override public void doKickout(String loginType, Object loginId, String tokenValue) { - String tenantId = Convert.toStr(StpUtil.getExtra(tokenValue, LoginHelper.TENANT_KEY)); - TenantHelper.dynamic(tenantId, () -> { - RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); - }); log.info("user doKickout, userId:{}, token:{}", loginId, tokenValue); } @@ -107,10 +88,6 @@ public class UserActionListener implements SaTokenListener { */ @Override public void doReplaced(String loginType, Object loginId, String tokenValue) { - String tenantId = Convert.toStr(StpUtil.getExtra(tokenValue, LoginHelper.TENANT_KEY)); - TenantHelper.dynamic(tenantId, () -> { - RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); - }); log.info("user doReplaced, userId:{}, token:{}", loginId, tokenValue); } diff --git a/ruoyi-site/ruoyi-gateway/src/main/java/org/dromara/gateway/handler/GatewayExceptionHandler.java b/ruoyi-site/ruoyi-gateway/src/main/java/org/dromara/gateway/handler/GatewayExceptionHandler.java index 375542811..e6aa58ac1 100644 --- a/ruoyi-site/ruoyi-gateway/src/main/java/org/dromara/gateway/handler/GatewayExceptionHandler.java +++ b/ruoyi-site/ruoyi-gateway/src/main/java/org/dromara/gateway/handler/GatewayExceptionHandler.java @@ -39,7 +39,7 @@ public class GatewayExceptionHandler implements ErrorWebExceptionHandler { msg = "内部服务器错误"; } - log.error("[网关异常处理]请求路径:{},异常信息:{}", exchange.getRequest().getPath(), ex.getMessage()); + log.error("[网关异常处理]请求路径:{},异常信息:{}", exchange.getRequest().getPath(), ex.getMessage(),ex); return WebFluxUtils.webFluxResponseWriter(response, msg); } diff --git a/ruoyi-site/ruoyi-sso-server/src/main/java/org/dromara/sso/listener/UserActionListener.java b/ruoyi-site/ruoyi-sso-server/src/main/java/org/dromara/sso/listener/UserActionListener.java index bffa2be6b..3bf61a81a 100644 --- a/ruoyi-site/ruoyi-sso-server/src/main/java/org/dromara/sso/listener/UserActionListener.java +++ b/ruoyi-site/ruoyi-sso-server/src/main/java/org/dromara/sso/listener/UserActionListener.java @@ -1,31 +1,25 @@ package org.dromara.sso.listener; -import cn.dev33.satoken.config.SaTokenConfig; import cn.dev33.satoken.listener.SaTokenListener; import cn.dev33.satoken.stp.SaLoginModel; import cn.dev33.satoken.stp.StpUtil; -import cn.hutool.core.convert.Convert; import cn.hutool.http.useragent.UserAgent; import cn.hutool.http.useragent.UserAgentUtil; +import org.dromara.common.core.constant.CacheConstants; import org.dromara.system.saas.api.model.SysSaasUserOnlineDTO; import org.dromara.sso.config.satoken.LoginSaasHelper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.dubbo.config.annotation.DubboReference; -import org.dromara.common.core.constant.CacheConstants; import org.dromara.common.core.constant.Constants; import org.dromara.common.core.utils.MessageUtils; import org.dromara.common.core.utils.ServletUtils; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.ip.AddressUtils; import org.dromara.common.log.event.LogininforEvent; -import org.dromara.common.redis.utils.RedisUtils; -import org.dromara.common.tenant.helper.TenantHelper; import org.dromara.system.saas.api.RemoteUserService; import org.springframework.stereotype.Component; -import java.time.Duration; - /** * 用户行为 侦听器的实现 * @@ -36,11 +30,8 @@ import java.time.Duration; @Slf4j public class UserActionListener implements SaTokenListener { - private final SaTokenConfig tokenConfig; @DubboReference private RemoteUserService remoteUserService; -// @DubboReference -// private RemoteMessageService remoteMessageService; /** * 每次登录时触发 @@ -49,6 +40,9 @@ public class UserActionListener implements SaTokenListener { public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) { UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent")); String ip = ServletUtils.getClientIP(); + String username = (String) loginModel.getExtra(LoginSaasHelper.USER_NAME_KEY); + String tenantId = (String) loginModel.getExtra(LoginSaasHelper.TENANT_KEY); + // 将用户信息作为对象存储到SaToken的会话中 SysSaasUserOnlineDTO userOnline = new SysSaasUserOnlineDTO(); userOnline.setIpaddr(ip); userOnline.setLoginLocation(AddressUtils.getRealAddressByIP(ip)); @@ -56,19 +50,12 @@ public class UserActionListener implements SaTokenListener { userOnline.setOs(userAgent.getOs().getName()); userOnline.setLoginTime(System.currentTimeMillis()); userOnline.setTokenId(tokenValue); - String username = (String) loginModel.getExtra(LoginSaasHelper.USER_NAME_KEY); - String tenantId = (String) loginModel.getExtra(LoginSaasHelper.TENANT_KEY); userOnline.setUserName(username); userOnline.setClientKey((String) loginModel.getExtra(LoginSaasHelper.CLIENT_KEY)); userOnline.setDeviceType(loginModel.getDevice()); userOnline.setDeptName((String) loginModel.getExtra(LoginSaasHelper.DEPT_NAME_KEY)); - TenantHelper.dynamic(tenantId, () -> { - if (tokenConfig.getTimeout() == -1) { - RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, userOnline); - } else { - RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, userOnline, Duration.ofSeconds(tokenConfig.getTimeout())); - } - }); + // 使用会话存储用户信息 + StpUtil.stpLogic.getTokenSessionByToken(tokenValue).set(CacheConstants.UserOnline, userOnline); // 记录登录日志 LogininforEvent logininforEvent = new LogininforEvent(); logininforEvent.setTenantId(tenantId); @@ -86,10 +73,6 @@ public class UserActionListener implements SaTokenListener { */ @Override public void doLogout(String loginType, Object loginId, String tokenValue) { - String tenantId = Convert.toStr(StpUtil.getExtra(tokenValue, LoginSaasHelper.TENANT_KEY)); - TenantHelper.dynamic(tenantId, () -> { - RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); - }); log.info("user doLogout, useId:{}, token:{}", loginId, tokenValue); } @@ -98,10 +81,6 @@ public class UserActionListener implements SaTokenListener { */ @Override public void doKickout(String loginType, Object loginId, String tokenValue) { - String tenantId = Convert.toStr(StpUtil.getExtra(tokenValue, LoginSaasHelper.TENANT_KEY)); - TenantHelper.dynamic(tenantId, () -> { - RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); - }); log.info("user doLogoutByLoginId, useId:{}, token:{}", loginId, tokenValue); } @@ -110,10 +89,6 @@ public class UserActionListener implements SaTokenListener { */ @Override public void doReplaced(String loginType, Object loginId, String tokenValue) { - String tenantId = Convert.toStr(StpUtil.getExtra(tokenValue, LoginSaasHelper.TENANT_KEY)); - TenantHelper.dynamic(tenantId, () -> { - RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); - }); log.info("user doReplaced, useId:{}, token:{}", loginId, tokenValue); }