From 25012e518e4ffc6ea1ed1f152670c858681b5b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 2 Jan 2024 20:10:40 +0800 Subject: [PATCH] =?UTF-8?q?[=E9=87=8D=E5=A4=A7=E6=9B=B4=E6=96=B0]=20?= =?UTF-8?q?=E4=BD=BF=E7=94=A8caffeine=E9=87=8D=E6=9E=84PlusSaTokenDao?= =?UTF-8?q?=E5=B1=82=E5=AE=9E=E7=8E=B0=20=E5=87=8F=E5=B0=91=E5=B0=86?= =?UTF-8?q?=E8=BF=9190%=E7=9A=84redis=E6=9F=A5=E8=AF=A2=E6=8F=90=E9=AB=98?= =?UTF-8?q?=E6=80=A7=E8=83=BD(=E5=B0=9D=E8=AF=95=E6=80=A7=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E9=97=AE=E9=A2=98=E6=9C=AA=E7=9F=A5=20=E8=AF=B7?= =?UTF-8?q?=E5=8B=BF=E8=BD=BB=E6=98=93=E6=9B=B4=E6=96=B0=E5=B0=9D=E8=AF=95?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/listener/UserActionListener.java | 22 +++---- ruoyi-common/ruoyi-common-satoken/pom.xml | 5 ++ .../satoken/core/dao/PlusSaTokenDao.java | 35 ++++++++++-- .../common/satoken/utils/LoginHelper.java | 57 +++++++------------ .../config/SecurityConfiguration.java | 10 +--- 5 files changed, 66 insertions(+), 63 deletions(-) diff --git a/ruoyi-auth/src/main/java/org/dromara/auth/listener/UserActionListener.java b/ruoyi-auth/src/main/java/org/dromara/auth/listener/UserActionListener.java index 86df42c73..79f43d1f7 100644 --- a/ruoyi-auth/src/main/java/org/dromara/auth/listener/UserActionListener.java +++ b/ruoyi-auth/src/main/java/org/dromara/auth/listener/UserActionListener.java @@ -3,7 +3,6 @@ package org.dromara.auth.listener; import cn.dev33.satoken.config.SaTokenConfig; import cn.dev33.satoken.listener.SaTokenListener; import cn.dev33.satoken.stp.SaLoginModel; -import cn.hutool.core.util.ObjectUtil; import cn.hutool.http.useragent.UserAgent; import cn.hutool.http.useragent.UserAgentUtil; import lombok.RequiredArgsConstructor; @@ -21,11 +20,9 @@ import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.resource.api.RemoteMessageService; import org.dromara.system.api.RemoteUserService; import org.dromara.system.api.domain.SysUserOnline; -import org.dromara.system.api.model.LoginUser; import org.springframework.stereotype.Component; import java.time.Duration; -import java.util.concurrent.ScheduledExecutorService; /** * 用户行为 侦听器的实现 @@ -38,7 +35,6 @@ import java.util.concurrent.ScheduledExecutorService; public class UserActionListener implements SaTokenListener { private final SaTokenConfig tokenConfig; - private final ScheduledExecutorService scheduledExecutorService; @DubboReference private RemoteUserService remoteUserService; @DubboReference @@ -51,7 +47,6 @@ 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(); - LoginUser user = LoginHelper.getLoginUser(); SysUserOnline userOnline = new SysUserOnline(); userOnline.setIpaddr(ip); userOnline.setLoginLocation(AddressUtils.getRealAddressByIP(ip)); @@ -59,12 +54,11 @@ public class UserActionListener implements SaTokenListener { userOnline.setOs(userAgent.getOs().getName()); userOnline.setLoginTime(System.currentTimeMillis()); userOnline.setTokenId(tokenValue); - userOnline.setUserName(user.getUsername()); - userOnline.setClientKey(user.getClientKey()); - userOnline.setDeviceType(user.getDeviceType()); - if (ObjectUtil.isNotNull(user.getDeptName())) { - userOnline.setDeptName(user.getDeptName()); - } + String username = (String) loginModel.getExtra(LoginHelper.USER_NAME_KEY); + userOnline.setUserName(username); + userOnline.setClientKey((String) loginModel.getExtra(LoginHelper.CLIENT_KEY)); + userOnline.setDeviceType(loginModel.getDevice()); + userOnline.setDeptName((String) loginModel.getExtra(LoginHelper.DEPT_NAME_KEY)); if (tokenConfig.getTimeout() == -1) { RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, userOnline); } else { @@ -72,14 +66,14 @@ public class UserActionListener implements SaTokenListener { } // 记录登录日志 LogininforEvent logininforEvent = new LogininforEvent(); - logininforEvent.setTenantId(user.getTenantId()); - logininforEvent.setUsername(user.getUsername()); + logininforEvent.setTenantId((String) loginModel.getExtra(LoginHelper.TENANT_KEY)); + logininforEvent.setUsername(username); logininforEvent.setStatus(Constants.LOGIN_SUCCESS); logininforEvent.setMessage(MessageUtils.message("user.login.success")); logininforEvent.setRequest(ServletUtils.getRequest()); SpringUtils.context().publishEvent(logininforEvent); // 更新登录信息 - remoteUserService.recordLoginInfo(user.getUserId(), ServletUtils.getClientIP()); + remoteUserService.recordLoginInfo((Long) loginModel.getExtra(LoginHelper.USER_KEY), ip); log.info("user doLogin, useId:{}, token:{}", loginId, tokenValue); } diff --git a/ruoyi-common/ruoyi-common-satoken/pom.xml b/ruoyi-common/ruoyi-common-satoken/pom.xml index 93d46eb86..733927be1 100644 --- a/ruoyi-common/ruoyi-common-satoken/pom.xml +++ b/ruoyi-common/ruoyi-common-satoken/pom.xml @@ -52,6 +52,11 @@ ruoyi-common-redis + + com.github.ben-manes.caffeine + caffeine + + diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java index d88596228..b262d07f0 100644 --- a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java +++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java @@ -2,12 +2,16 @@ package org.dromara.common.satoken.core.dao; import cn.dev33.satoken.dao.SaTokenDao; import cn.dev33.satoken.util.SaFoxUtil; +import cn.hutool.core.lang.Console; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; import org.dromara.common.redis.utils.RedisUtils; import java.time.Duration; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.concurrent.TimeUnit; /** * Sa-Token持久层接口(使用框架自带RedisUtils实现 协议统一) @@ -16,12 +20,23 @@ import java.util.List; */ public class PlusSaTokenDao implements SaTokenDao { + private static final Cache CAFFEINE = Caffeine.newBuilder() + // 设置最后一次写入或访问后经过固定时间过期 + .expireAfterWrite(10, TimeUnit.SECONDS) + // 初始的缓存空间大小 + .initialCapacity(100) + // 缓存的最大条数 + .maximumSize(1000) + .build(); + /** * 获取Value,如无返空 */ @Override public String get(String key) { - return RedisUtils.getCacheObject(key); + Object o = CAFFEINE.get(key, k -> RedisUtils.getCacheObject(key)); + Console.log("caffeine -> key:" + key + ",value:" + o); + return (String) o; } /** @@ -38,6 +53,7 @@ public class PlusSaTokenDao implements SaTokenDao { } else { RedisUtils.setCacheObject(key, value, Duration.ofSeconds(timeout)); } + CAFFEINE.put(key, value); } /** @@ -47,6 +63,7 @@ public class PlusSaTokenDao implements SaTokenDao { public void update(String key, String value) { if (RedisUtils.hasKey(key)) { RedisUtils.setCacheObject(key, value, true); + CAFFEINE.put(key, value); } } @@ -81,7 +98,9 @@ public class PlusSaTokenDao implements SaTokenDao { */ @Override public Object getObject(String key) { - return RedisUtils.getCacheObject(key); + Object o = CAFFEINE.get(key, k -> RedisUtils.getCacheObject(key)); + Console.log("caffeine -> key:" + key + ",value:" + o); + return o; } /** @@ -98,6 +117,7 @@ public class PlusSaTokenDao implements SaTokenDao { } else { RedisUtils.setCacheObject(key, object, Duration.ofSeconds(timeout)); } + CAFFEINE.put(key, object); } /** @@ -107,6 +127,7 @@ public class PlusSaTokenDao implements SaTokenDao { public void updateObject(String key, Object object) { if (RedisUtils.hasKey(key)) { RedisUtils.setCacheObject(key, object, true); + CAFFEINE.put(key, object); } } @@ -139,10 +160,14 @@ public class PlusSaTokenDao implements SaTokenDao { /** * 搜索数据 */ + @SuppressWarnings("unchecked") @Override public List searchData(String prefix, String keyword, int start, int size, boolean sortType) { - Collection keys = RedisUtils.keys(prefix + "*" + keyword + "*"); - List list = new ArrayList<>(keys); - return SaFoxUtil.searchList(list, start, size, sortType); + String keyStr = prefix + "*" + keyword + "*"; + return (List) CAFFEINE.get(keyStr, k -> { + Collection keys = RedisUtils.keys(keyStr); + List list = new ArrayList<>(keys); + return SaFoxUtil.searchList(list, start, size, sortType); + }); } } diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java index 703936f45..568e7b6c8 100644 --- a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java +++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java @@ -9,12 +9,10 @@ import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.dromara.common.core.constant.TenantConstants; import org.dromara.common.core.constant.UserConstants; -import org.dromara.common.core.context.ThreadLocalHolder; import org.dromara.common.core.enums.UserType; import org.dromara.system.api.model.LoginUser; import java.util.Set; -import java.util.function.Supplier; /** * 登录鉴权助手 @@ -34,9 +32,10 @@ public class LoginHelper { public static final String LOGIN_USER_KEY = "loginUser"; public static final String TENANT_KEY = "tenantId"; public static final String USER_KEY = "userId"; + public static final String USER_NAME_KEY = "userName"; public static final String DEPT_KEY = "deptId"; + public static final String DEPT_NAME_KEY = "deptName"; public static final String CLIENT_KEY = "clientid"; - public static final String TENANT_ADMIN_KEY = "isTenantAdmin"; /** * 登录系统 基于 设备类型 @@ -46,15 +45,15 @@ public class LoginHelper { * @param model 配置参数 */ public static void login(LoginUser loginUser, SaLoginModel model) { - ThreadLocalHolder.set(LOGIN_USER_KEY, loginUser); - ThreadLocalHolder.set(TENANT_KEY, loginUser.getTenantId()); - ThreadLocalHolder.set(USER_KEY, loginUser.getUserId()); - ThreadLocalHolder.set(DEPT_KEY, loginUser.getDeptId()); model = ObjectUtil.defaultIfNull(model, new SaLoginModel()); StpUtil.login(loginUser.getLoginId(), model.setExtra(TENANT_KEY, loginUser.getTenantId()) .setExtra(USER_KEY, loginUser.getUserId()) - .setExtra(DEPT_KEY, loginUser.getDeptId())); + .setExtra(DEPT_KEY, loginUser.getDeptId()) + .setExtra(TENANT_KEY, loginUser.getTenantId()) + .setExtra(DEPT_NAME_KEY, loginUser.getDeptName()) + .setExtra(USER_NAME_KEY, loginUser.getUsername()) + ); SaSession tokenSession = StpUtil.getTokenSession(); tokenSession.updateTimeout(model.getTimeout()); tokenSession.set(LOGIN_USER_KEY, loginUser); @@ -64,13 +63,11 @@ public class LoginHelper { * 获取用户(多级缓存) */ public static LoginUser getLoginUser() { - return (LoginUser) getStorageIfAbsentSet(LOGIN_USER_KEY, () -> { - SaSession session = StpUtil.getTokenSession(); - if (ObjectUtil.isNull(session)) { - return null; - } - return session.get(LOGIN_USER_KEY); - }); + SaSession session = StpUtil.getTokenSession(); + if (ObjectUtil.isNull(session)) { + return null; + } + return (LoginUser) session.get(LOGIN_USER_KEY); } /** @@ -88,7 +85,7 @@ public class LoginHelper { * 获取用户id */ public static Long getUserId() { - return Convert.toLong(getExtra(USER_KEY)); + return Convert.toLong(getExtra(USER_KEY)); } /** @@ -106,7 +103,12 @@ public class LoginHelper { } private static Object getExtra(String key) { - return getStorageIfAbsentSet(key, () -> StpUtil.getExtra(key)); + try { + return StpUtil.getExtra(key); + } catch (Exception e) { + return null; + } + } /** @@ -120,8 +122,8 @@ public class LoginHelper { * 获取用户类型 */ public static UserType getUserType() { - String loginId = StpUtil.getLoginIdAsString(); - return UserType.getUserType(loginId); + String loginType = StpUtil.getLoginIdAsString(); + return UserType.getUserType(loginType); } /** @@ -149,26 +151,11 @@ public class LoginHelper { } public static boolean isTenantAdmin() { - Object value = getStorageIfAbsentSet(TENANT_ADMIN_KEY, () -> { - return isTenantAdmin(getLoginUser().getRolePermission()); - }); - return Convert.toBool(value); + return Convert.toBool(isTenantAdmin(getLoginUser().getRolePermission())); } public static boolean isLogin() { return getLoginUser() != null; } - public static Object getStorageIfAbsentSet(String key, Supplier handle) { - try { - Object obj = ThreadLocalHolder.get(key); - if (ObjectUtil.isNull(obj)) { - obj = handle.get(); - ThreadLocalHolder.set(key, obj); - } - return obj; - } catch (Exception e) { - return null; - } - } } diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/org/dromara/common/security/config/SecurityConfiguration.java b/ruoyi-common/ruoyi-common-security/src/main/java/org/dromara/common/security/config/SecurityConfiguration.java index aed689df8..efd34fc2d 100644 --- a/ruoyi-common/ruoyi-common-security/src/main/java/org/dromara/common/security/config/SecurityConfiguration.java +++ b/ruoyi-common/ruoyi-common-security/src/main/java/org/dromara/common/security/config/SecurityConfiguration.java @@ -5,10 +5,7 @@ import cn.dev33.satoken.filter.SaServletFilter; import cn.dev33.satoken.interceptor.SaInterceptor; import cn.dev33.satoken.same.SaSameUtil; import cn.dev33.satoken.util.SaResult; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import org.dromara.common.core.constant.HttpStatus; -import org.dromara.common.core.context.ThreadLocalHolder; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; @@ -28,12 +25,7 @@ public class SecurityConfiguration implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { // 注册路由拦截器,自定义验证规则 - registry.addInterceptor(new SaInterceptor() { - @Override - public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { - ThreadLocalHolder.clear(); - } - }).addPathPatterns("/**"); + registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**"); } /**