spring security中动态更新用户的权限
在程序的执行过程中,有时有这么一种需求,需要动态的更新某些角色的权限或某些人对应的权限,当前在线的用户拥有这个角色或拥有这个权限时,在不退出系统的情况下,需要动态的改变的他所拥有的权限。
需求:张三 登录了系统拥有 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);
}
到此,应该就可以实现动态的修改在线用户的权限信息了。
注意:上面的代码有些是不全的,但是大致思路是这样的。
spring security中动态更新用户的权限的更多相关文章
- 在realm中动态查询用户的权限&角色
@Controller @Scope("prototype") @Namespace("/") @ParentPackage("struts-defa ...
- 项目一:第十三天 1、菜单数据管理 2、权限数据管理 3、角色数据管理 4、用户数据管理 5、在realm中动态查询用户权限,角色 6、Shiro中整合ehcache缓存权限数据
1 课程计划 菜单数据管理 权限数据管理 角色数据管理 用户数据管理 在realm中动态查询用户权限,角色 Shiro中整合ehcache缓存权限数据 2 菜单数据添加 2.1 使用c ...
- Spring Security之动态配置资源权限
在Spring Security中实现通过数据库动态配置url资源权限,需要通过配置验证过滤器来实现资源权限的加载.验证.系统启动时,到数据库加载系统资源权限列表,当有请求访问时,通过对比系统资源权限 ...
- SpringBoot Spring Security 核心组件 认证流程 用户权限信息获取详细讲解
前言 Spring Security 是一个安全框架, 可以简单地认为 Spring Security 是放在用户和 Spring 应用之间的一个安全屏障, 每一个 web 请求都先要经过 Sprin ...
- spring security实现动态配置url权限的两种方法
缘起 标准的RABC, 权限需要支持动态配置,spring security默认是在代码里约定好权限,真实的业务场景通常需要可以支持动态配置角色访问权限,即在运行时去配置url对应的访问角色. 基于s ...
- [收藏]Spring Security中的ACL
ACL即访问控制列表(Access Controller List),它是用来做细粒度权限控制所用的一种权限模型.对ACL最简单的描述就是两个业务员,每个人只能查看操作自己签的合同,而不能看到对方的合 ...
- 基于spring security 实现前后端分离项目权限控制
前后端分离的项目,前端有菜单(menu),后端有API(backendApi),一个menu对应的页面有N个API接口来支持,本文介绍如何基于spring security实现前后端的同步权限控制. ...
- 看源码,重新审视Spring Security中的角色(roles)是怎么回事
在网上看见不少的博客.技术文章,发现大家对于Spring Security中的角色(roles)存在较大的误解,最大的误解就是没有搞清楚其中角色和权限的差别(好多人在学习Spring Security ...
- springBoot整合spring security+JWT实现单点登录与权限管理--筑基中期
写在前面 在前一篇文章当中,我们介绍了springBoot整合spring security单体应用版,在这篇文章当中,我将介绍springBoot整合spring secury+JWT实现单点登录与 ...
随机推荐
- JPA实现泛型baseServcie+Mybatis
在开发的过程中,我们总无法避免不同的实体类会去实现相同的操作(增删查改,分页查询等),因此在开发时,我们期望泛型将通用的方法进行包装,使我们能够专注于实体类自身的独特方法,而非一般性常用且重复性高的方 ...
- 植入式Web前端开发
在博客园.凡科建站和其他的一些CMS系统中,提供有允许管理者向网页中插入自定义HTML代码的功能,我将其称之为"植入式"的Web前端代码. 因为CSS和JavaScript可以直接 ...
- 这些解决 Bug 的套路,你都会了不?
最近整理了我原创的 140 篇编程经验和技术文章,欢迎大家阅读,一起成长!指路:https://t.1yb.co/ARnD 大家好,我是鱼皮. 学编程的过程中,我们会遇到各式各样的 Bug,也常常因为 ...
- 基于Typora的Latex代码书写并移植到word中
如何使用Markdown编译器 编辑Latex公式 并嵌入word内 前言:对于科研党来讲,在论文中数学公式的展示是必不可少的一环,但是如果不使用公式的格式去敲,那么公式就会过于难看,会大大降低你 ...
- Python简单算法的实现
#coding=utf-8 #!/usr/bin/python def GCD(a,b): """ :求两个数的最大公约数 :param a: :param b: :re ...
- frida的安装教程-配合夜神模拟器
Frida安装 一.PC端安装 1. 安装frida 默认安装最新版的Frida pip install frida 因为我用的是夜神模拟器,可能不支持最新版,所以下载的之前版本. pip insta ...
- aizhan查询旁IP网站脚本
<?php print_r("-------------------------\r\n"); print_r("-------爱站旁站查询------\r\n&q ...
- 【死磕NIO】— 阻塞IO,非阻塞IO,IO复用,信号驱动IO,异步IO,这你真的分的清楚吗?
通过上篇文章([死磕NIO]- 阻塞.非阻塞.同步.异步,傻傻分不清楚),我想你应该能够区分了什么是阻塞.非阻塞.异步.非异步了,这篇文章我们来彻底弄清楚什么是阻塞IO,非阻塞IO,IO复用,信号驱动 ...
- JavaFx 监听剪切板实现(Kotlin)
原文地址: JavaFx 监听剪切板实现(Kotlin) | Stars-One的杂货小窝 软件有个需求,想要实现监听剪切板的内容,若内容符合预期,则进行相关的操作,就可以免去用户手动粘贴的操作,提供 ...
- 面试官问我MySQL调优,我真的是
面试官:要不你来讲讲你们对MySQL是怎么调优的? 候选者:哇,这命题很大阿...我认为,对于开发者而言,对MySQL的调优重点一般是在「开发规范」.「数据库索引」又或者说解决线上慢查询上. 候选者: ...