在程序的执行过程中,有时有这么一种需求,需要动态的更新某些角色的权限或某些人对应的权限,当前在线的用户拥有这个角色或拥有这个权限时,在不退出系统的情况下,需要动态的改变的他所拥有的权限。
需求:张三 登录了系统拥有 ROLE_ADMIN,和ROLE_USER 的权限,但是ROLE_ADMIN的权限太强了,不应该给张三,后台管理人员应该可以取消张三的ROLE_ADMIN的权限,那么在张三还在线且没有退出系统的情况下应该不可以继续访问ROLE_ADMIN的权限的资源。
解决思路:
1、监听系统中所有的在线用户,需要监听session的创建和销毁事件
2、spring secuirty在登录成功后为了防止session的固化攻击会改变sessionId的值,因此需要监听spring security发布的 SessionFixationProtectionEvent事件
3、当我们系统中的资源发生了改变时,需要发布自己的一个资源改变事件,在此事件中修改当前在线用户的权限。
大致步骤如下:
一、拿到系统中所有的在线用户对象
|- 将 HttpSessionEventPublisher 注册成一个listener,注册之后就可以监听到session的创建和销毁事件
/** * 注册Servlet Listener,用于发布Session的创建和销毁事件 */ @Bean public ServletListenerRegistrationBean httpSessionEventPublisher() { ServletListenerRegistrationBean<HttpSessionEventPublisher> registration = new ServletListenerRegistrationBean<>(); registration.setListener(new HttpSessionEventPublisher()); return registration; }
|- 监听session的创建事件(HttpSessionCreatedEvent),在这一步需要保存session对象
/** * 监听session创建对象 */ @Component @Slf4j class HttpSessionCreatedEventListener implements ApplicationListener<HttpSessionCreatedEvent> { @Override public void onApplicationEvent(HttpSessionCreatedEvent event) { log.info("新建session:{}", event.getSession().getId()); try { // 保存 session } catch (Exception e) { log.info(String.format("添加session:[%s]出现异常.", event.getSession().getId()), e); } } }
|- 监听session的销毁事件(HttpSessionDestroyedEvent),此事件主要是移除没有的session对象
/** * 监听session失效事件 */ @Component @Slf4j class SessionDestroyedEventListener implements ApplicationListener<HttpSessionDestroyedEvent> { @Override public void onApplicationEvent(HttpSessionDestroyedEvent event) { log.info("失效session:{}", event.getSession().getId()); try { // 移除session } catch (Exception e) { log.error(String.format("失效session:[%s]发生异常.", event.getId()), e); } } }
|- 保存系统中所有的session对象
二、监听SessionFixationProtectionEvent事件,这个主要是spring security为了防止session的固化攻击,在用户登录成功后,会修改用户的sessionId的值,并发布此事件,需要在此监听,不然上一步保存的session中的sessionId的值是有问题的。
(注:可以查看org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter#sessionStrategy这个)
/** * @author huan.fu * Spring security 登录成功后,防止session的固化攻击,会将旧的sessionId销毁,重新生成一个新的sessionId, * 因此此处需要做一下处理 */ @Component class SessionFixationProtectionEventListener implements ApplicationListener<SessionFixationProtectionEvent> { @Override public void onApplicationEvent(SessionFixationProtectionEvent event) { String oldSessionId = event.getOldSessionId(); String newSessionId = event.getNewSessionId(); // 更改sessionId的值 } }
三、当系统中的资源发生改变时,修改当前在线用户的资源
有了上面2步的基础,可以获取到当前所有在线的用户对象,当我们自己系统中的资源发生了改变的时候,比如给用户增加了一个新的角色,删除了用户的一个角色,或者给角色新增加或删除了资源时,我们就可以对当前当前用户做一些处理(比如过滤没有这个权限的用户,当session还是新建的时候的处理等),来动态更新用户的权限。
获取当前用户信息:
1、从session中获取:
SecurityContext securityContext = (SecurityContext) session.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY); Object principal = securityContext.getAuthentication().getPrincipal();
2、重新加载当前用户的资源
/** * 重新加载用户的权限 * * @param session */ private void reloadUserAuthority(HttpSession session) { // 新的权限 List<GrantedAuthority> authorityList = AuthorityUtils.createAuthorityList(new String[]{"从数据库中查询出来"}); SecurityContext securityContext = (SecurityContext) session.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY); Authentication authentication = securityContext.getAuthentication(); SecurityUser principal = (SecurityUser) authentication.getPrincipal(); principal.setAuthorities(authorityList); // 重新new一个token,因为Authentication中的权限是不可变的. UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken( principal, authentication.getCredentials(), authorityList); result.setDetails(authentication.getDetails()); securityContext.setAuthentication(result); }
到此,应该就可以实现动态的修改在线用户的权限信息了。
注意:上面的代码有些是不全的,但是大致思路是这样的。
相关推荐
在这个“springboot springsecurity动态权限控制”的主题中,我们将深入探讨如何在Spring Boot项目中集成Spring Security,实现动态权限控制,让菜单权限的管理更加灵活和高效。 首先,我们需要理解Spring Security...
然而,通过动态授权,我们可以将用户、角色和资源信息存储在数据库中,允许在运行时动态配置权限,而无需重启服务,从而极大地提高了灵活性。 动态授权的核心在于权限模型的设计。在Spring Security中,我们通常...
其中,权限控制是Spring Security的一个重要组件,它允许开发者根据用户角色和权限来控制访问不同的资源。在本文中,我们将探讨如何使用Spring Security来实现URL地址的权限控制。 权限控制是指根据用户的角色和...
struts2 + spring3 + hibernate3 + spring security3 + mysql + tomcat sys_users;sys_roles;sys_authorities;sys_resources;sys_users_roles;sys_roles_authorities;sys_authorities_resources; PS:此项目运行不...
在这个项目中,SpringSecurity被用来处理用户登录、角色权限分配和防止非法请求。 3. **JPA**:Java Persistence API是Java平台上的ORM(对象关系映射)规范,它允许开发者以面向对象的方式操作数据库,将数据对象...
在这个项目中,这三者协同工作,Spring Security 负责后台的权限控制,Spring MVC 处理业务逻辑和数据交互,而 jQuery Easy-UI 则提供了用户友好的界面。理解这些知识点对于开发和维护这样一个用户权限管理项目至关...
在本文中,我们将深入探讨如何使用Spring Boot、Spring Security和MyBatis这三大技术栈来实现用户权限的数据库动态管理。这是一个常见的需求,在许多企业级应用中,动态管理用户权限可以提高系统的灵活性和可扩展性...
SecurityContext 是 Spring Security 中的一个重要概念,表示当前用户的安全上下文。SecurityContext 中包含用户的身份信息、权限信息等。SecurityContext 是通过 SecurityContextHolder 实现的。 五、Spring ...
在本文中,我们将深入探讨如何在Spring Security 3中实现多用户登录功能。首先,我们需要理解Spring Security的基本架构和核心概念。 1. **Spring Security 架构** Spring Security的核心组件包括: - **Filter ...
在Spring Security中,"角色"是赋予用户的标识,表示用户在系统中的职责或权限集合。例如,"管理员"、"用户"等。"权限"则更加具体,代表用户可以执行的操作,如"查看报告"、"编辑内容"等。角色通常包含一组权限,...
在本文中,我们将深入探讨如何使用Spring Boot、Spring Security和Thymeleaf这三个强大的Java技术栈组件来实现一个全面的权限管理系统,同时涵盖Remember-Me功能。Spring Boot简化了Spring应用的开发,Spring ...
本文将详细探讨SpringSecurity中关于自定义用户权限信息存取的实现方法,包括如何通过配置文件和数据库来管理用户的认证信息和权限数据。 首先,当我们谈论用户权限信息的存取,实际上是在处理两个方面的问题:用户...
使用spring security解决用户权限的方案
SpringSecurity是Java开发领域中广泛使用的安全框架,用于保护Web应用程序免受各种安全威胁。它提供了全面的身份验证、授权和访问控制功能。本压缩包包含了两份重要的SpringSecurity中文文档,分别为“Spring ...
在"SpringSecurity权限管理开发手册.pdf"和"SpringSecurity权限管理开发手册.pdf.txt"中,你将找到更多关于如何配置和使用SpringSecurity进行权限管理的详细信息,包括配置XML或Java配置、定义访问规则、处理未授权...
在用户、角色、权限、菜单之间,存在复杂的多对多关系,因此Spring Security需要相应的数据模型来支持这些关系,这通常涉及用户表、角色表、权限表、菜单表、以及它们之间的关联表。 Spring Security架构中的角色表...
4. **访问控制表达式(Access Control Expressions, ACEs)**:Spring Security的SpEL允许在配置中使用表达式来定义访问规则,如`@Secured("hasRole('ROLE_ADMIN')"`,这表示只有拥有'ROLE_ADMIN'角色的用户才能访问...
在本文中,我们将深入探讨Spring Security如何实现权限控制,并通过一个名为"springsecuritydemo4"的示例项目来理解其核心概念。 首先,Spring Security 的权限控制主要涉及以下几个关键组件: 1. **认证...
在"spring security权限管理"这个主题中,我们将深入探讨如何利用Spring Security来实现复杂而灵活的权限控制。 首先,`MyUser.java`可能是自定义的用户实体类,它通常会包含用户的基本信息,如用户名、密码、角色...