From d349d10d458887a25513156e2e055d099f2c1377 Mon Sep 17 00:00:00 2001 From: XuYang <14706323104@163.com> Date: Mon, 22 Jul 2024 10:14:55 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=A3=E5=86=B3cookie[rememberMe]=E9=95=BF?= =?UTF-8?q?=E5=BA=A6=E5=A4=A7=E4=BA=8E4KB=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ruoyi/framework/config/ShiroConfig.java | 6 +- .../CustomCookieRememberMeManager.java | 91 +++++++++++++++++++ 2 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/rememberMe/CustomCookieRememberMeManager.java diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java index 2f487fa82..8bee6949e 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java @@ -15,7 +15,6 @@ import org.apache.shiro.io.ResourceUtils; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; -import org.apache.shiro.web.mgt.CookieRememberMeManager; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.apache.shiro.web.servlet.SimpleCookie; import org.springframework.beans.factory.annotation.Qualifier; @@ -38,6 +37,7 @@ import com.ruoyi.framework.shiro.web.filter.online.OnlineSessionFilter; import com.ruoyi.framework.shiro.web.filter.sync.SyncOnlineSessionFilter; import com.ruoyi.framework.shiro.web.session.OnlineWebSessionManager; import com.ruoyi.framework.shiro.web.session.SpringSessionValidationScheduler; +import com.ruoyi.framework.shiro.rememberMe.CustomCookieRememberMeManager; import at.pollux.thymeleaf.shiro.dialect.ShiroDialect; /** @@ -369,9 +369,9 @@ public class ShiroConfig /** * 记住我 */ - public CookieRememberMeManager rememberMeManager() + public CustomCookieRememberMeManager rememberMeManager() { - CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); + CustomCookieRememberMeManager cookieRememberMeManager = new CustomCookieRememberMeManager(); cookieRememberMeManager.setCookie(rememberMeCookie()); if (StringUtils.isNotEmpty(cipherKey)) { diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/rememberMe/CustomCookieRememberMeManager.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/rememberMe/CustomCookieRememberMeManager.java new file mode 100644 index 000000000..d6263b631 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/rememberMe/CustomCookieRememberMeManager.java @@ -0,0 +1,91 @@ +package com.ruoyi.framework.shiro.rememberMe; + +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.framework.shiro.service.SysLoginService; +import org.apache.shiro.subject.PrincipalCollection; +import org.apache.shiro.subject.Subject; +import org.apache.shiro.subject.SubjectContext; +import org.apache.shiro.web.mgt.CookieRememberMeManager; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * 自定义CookieRememberMeManager,干预序列化cookie[rememberMe]时的流程 + * + * @author XuYang + */ +public class CustomCookieRememberMeManager extends CookieRememberMeManager +{ + + private final SysLoginService sysLoginService = SpringUtils.getBean(SysLoginService.class); + + /** + * 序列化 cookie[rememberMe]的逻辑 + * 序列化的时候去掉角色的Permissions权限字符串 + * 因为accountPrincipals中的Principals对象和Subject中的Principals对象是同一个, + * 如果只清除权限不恢复权限会导致正常登录后的subject中的role也没有权限字符,所以还得恢复一下。 + */ + @Override + protected void rememberIdentity(Subject subject, PrincipalCollection accountPrincipals) + { + // 创建一个临时对象来存储原始的权限信息 + Map> originalPermissions = new HashMap<>(); + // 清除权限信息 + for (Object principal : accountPrincipals) + { + if (principal instanceof SysUser) + { + List roles = ((SysUser) principal).getRoles(); + for (SysRole role : roles) + { + originalPermissions.put(role, role.getPermissions()); + role.setPermissions(null); + } + } + } + // 将accountPrincipals转换为字节数组,后续流程会再转base64 + byte[] bytes = convertPrincipalsToBytes(accountPrincipals); + // 恢复权限信息 + for (Object principal : accountPrincipals) + { + if (principal instanceof SysUser) + { + List roles = ((SysUser) principal).getRoles(); + for (SysRole role : roles) + { + role.setPermissions(originalPermissions.get(role)); + } + } + } + rememberSerializedIdentity(subject, bytes); + } + + /** + * 反序列化 cookie[rememberMe]的逻辑 + * 本方法只会在【cookie中只携带了rememberMe,没有携带JSESSIONID】的情况下执行一次, + * 执行后就会生成新的JSESSIONID返回给客户端,后续就不会再执行本方法。 + */ + @Override + public PrincipalCollection getRememberedPrincipals(SubjectContext subjectContext) + { + PrincipalCollection principals = super.getRememberedPrincipals(subjectContext); + if (principals == null || principals.isEmpty()) + { + return principals; + } + // 序列化的时候把权限字符串去掉了,这里存上 + for (Object principal : principals) + { + if (principal instanceof SysUser) + { + sysLoginService.setRolePermission((SysUser) principal); + } + } + return principals; + } +}