在程序的执行过程中,有时有这么一种需求,需要动态的更新某些角色的权限或某些人对应的权限,当前在线的用户拥有这个角色或拥有这个权限时,在不退出系统的情况下,需要动态的改变的他所拥有的权限。

需求:张三 登录了系统拥有 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中动态更新用户的权限的更多相关文章

  1. 在realm中动态查询用户的权限&角色

    @Controller @Scope("prototype") @Namespace("/") @ParentPackage("struts-defa ...

  2. 项目一:第十三天 1、菜单数据管理 2、权限数据管理 3、角色数据管理 4、用户数据管理 5、在realm中动态查询用户权限,角色 6、Shiro中整合ehcache缓存权限数据

    1 课程计划 菜单数据管理 权限数据管理 角色数据管理 用户数据管理 在realm中动态查询用户权限,角色 Shiro中整合ehcache缓存权限数据         2 菜单数据添加 2.1 使用c ...

  3. Spring Security之动态配置资源权限

    在Spring Security中实现通过数据库动态配置url资源权限,需要通过配置验证过滤器来实现资源权限的加载.验证.系统启动时,到数据库加载系统资源权限列表,当有请求访问时,通过对比系统资源权限 ...

  4. SpringBoot Spring Security 核心组件 认证流程 用户权限信息获取详细讲解

    前言 Spring Security 是一个安全框架, 可以简单地认为 Spring Security 是放在用户和 Spring 应用之间的一个安全屏障, 每一个 web 请求都先要经过 Sprin ...

  5. spring security实现动态配置url权限的两种方法

    缘起 标准的RABC, 权限需要支持动态配置,spring security默认是在代码里约定好权限,真实的业务场景通常需要可以支持动态配置角色访问权限,即在运行时去配置url对应的访问角色. 基于s ...

  6. [收藏]Spring Security中的ACL

    ACL即访问控制列表(Access Controller List),它是用来做细粒度权限控制所用的一种权限模型.对ACL最简单的描述就是两个业务员,每个人只能查看操作自己签的合同,而不能看到对方的合 ...

  7. 基于spring security 实现前后端分离项目权限控制

    前后端分离的项目,前端有菜单(menu),后端有API(backendApi),一个menu对应的页面有N个API接口来支持,本文介绍如何基于spring security实现前后端的同步权限控制. ...

  8. 看源码,重新审视Spring Security中的角色(roles)是怎么回事

    在网上看见不少的博客.技术文章,发现大家对于Spring Security中的角色(roles)存在较大的误解,最大的误解就是没有搞清楚其中角色和权限的差别(好多人在学习Spring Security ...

  9. springBoot整合spring security+JWT实现单点登录与权限管理--筑基中期

    写在前面 在前一篇文章当中,我们介绍了springBoot整合spring security单体应用版,在这篇文章当中,我将介绍springBoot整合spring secury+JWT实现单点登录与 ...

随机推荐

  1. echo -e 命令详解

    echo在php中是输入那么在linux中是不是也是输入呢,当然echo在linux也是输入不过它的用法比php强大多了可以带参数及一些东西,下面我们来看一篇关于linux echo命令介绍及-n.- ...

  2. 【数据库上】第五讲 E-R模型扩展知识

    第五讲 E-R模型扩展知识 一.E-R模型设计主意问题 1.1 用实体还是实体集 案例:学院对象的表示 应将各个学院看做实体集,还是实体? 方法一:将各个学院看作一个实体集 如果各学院具有不同属性特征 ...

  3. 为什么要设置GOROOT/GOPATH

    设置GOROOT的原因 编译器的位置指定的时候,需要指定GO开发包的安装位置,然后设置环境变量PATH的时候,需要指定到安装包下的bin目录,其中就有以下的编译/执行器.所以GOROOT指定了前面的路 ...

  4. Java 简介与安装、语法说明、数据类型

    目录 Java 介绍 Java 简介 Java 语言跨平台原理 JRE 和 JDK JDK 下载/安装说明 Java 语法说明 注释 关键字 标识符 数据类型 基本数据类型 引用数据类型 隐式类型转换 ...

  5. vue随记

    (一)使用props传值: <HeadTitle name-data="100"></HeadTitle> props:['nameData'] 父组件传递 ...

  6. Collections集合工具类和可变参数

    Collections常用的API: public static <T> boolean addAll(Collection<? super T> c, T... elemen ...

  7. 洛谷P1603——斯诺登的密码(字符串处理)

    https://www.luogu.org/problem/show?pid=1603#sub 题目描述 2013年X月X日,俄罗斯办理了斯诺登的护照,于是他混迹于一架开往委内瑞拉的飞机.但是,这件事 ...

  8. spring入门1-IOC和DI

    1.概述 1.1.简介 Spring是分层的 Java SE/EE应用 full-stack 轻量级开源框架,以 IoC(Inverse Of Control:反转控制)和 AOP(Aspect Or ...

  9. SVN服务器的环境搭建(图文并茂)

    SVN服务器的搭建与使用 本章读完,就可以创建代码版本库,传送门 https://www.cnblogs.com/zzpython/p/13348009.html TortoiseSVN 是 Subv ...

  10. 初探计算机网络之CPU和内存

    CPU ​ CPU是一块超大规模的集成电路板,是计算机的核心部件,承载着计算机的主要运算和控制功能,是计算机的最终解释模块和执行模块.总之,用一句话概括就是,CPU是由控制器和运算器组成的,而内部寄存 ...