spring security 动态 修改当前登录用户的 权限
1.前言
spring security 可以获取当前登录的用户信息,同时提供了接口 来修改权限列表信息 ,
使用这个方法 ,可以动态的修改当前登录用户权限。
那么问题来了。。。
如果我是管理员 ,如何动态地修改用户的权限?比如vip权限?
按照以前的权限使用方法 ,修改数据库的权限信息后,当前用户需要重新登录,才能从数据库获取新的权限信息后再更新当前用户的权限列表,一般是管理员修改权限后,强制用户重新登录,
这样对用户很不友好 ,使用spring security 可以直接更新当前用户的权限 ,其实就是重新注册权限列表信息。
可是问题又来了。。。
spring security 不是只能修改当前登录用户的信息么?那么怎么修改别人的?
有两个解决方案:
(1)方案一:管理员在数据库修改用户权限数据后,检查该用户是否已经登录,未登录则操作结束,
如果已经登录,则使用websocket通知用户前端向后端Ajax发送一个修改当前权限的请求。
(2)方案二:管理员在数据库修改用户权限数据,检查该用户是否已经登录,未登录则操作结束,
如果已经登录,获取当前用户存在内存的session,根据session获取该用户的认证信息 ,取出权限列表后对其修改,然后重新注册权限列表。
2.操作
准备一个配置好的spring boot+ spring security的工程 ,详细操作这里不演示 ,在我的其他随笔有详细记录
(1)目录结构

(2)添加方法

源码
package com.example.security5500.controller; import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController; import java.security.Principal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; /**
* 作为授权类 ,用来动态更新权限
*/
@RestController
public class AuthorityController { //添加权限 ,参数是需要新增的权限名
@RequestMapping("/addAuth")
public Map<String,Object> addAuth(String authName){
Map<String,Object> map = new HashMap<>();
if (StringUtils.isBlank(authName)){
map.put("data","权限名称不可空,参数名authName");
return map;
} try {
//========================================================
//这一段仅仅是更新当前登录用户的权限列表 ,登出后将释放 ,当再次从数据库获取权限数据时将还原 ,因此如果需要持久性的更改权限,
// 还需要修改数据库信息 ,懒得写 ,这里就不做修改数据库演示了
//
// 得到当前的认证信息
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
// 生成当前的所有授权
List<GrantedAuthority> updatedAuthorities = new ArrayList<>(auth.getAuthorities());
// 添加 ROLE_VIP 授权
updatedAuthorities.add(new SimpleGrantedAuthority("ROLE_" + authName));
// 生成新的认证信息
Authentication newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(), updatedAuthorities);
// 重置认证信息
SecurityContextHolder.getContext().setAuthentication(newAuth);
//========================================================
map.put("data","权限 "+authName+" 添加成功");
}catch (Exception e){
e.printStackTrace();
map.put("data","权限添加失败");
}
return map;
} //获取用户权限信息
@RequestMapping({"/info"})
@ResponseBody
public Object info(@AuthenticationPrincipal Principal principal) {
return principal;
}
/*
{"authorities":[{"authority":"admin"},{"authority":"user"}],
"details":{"remoteAddress":"0:0:0:0:0:0:0:1","sessionId":"1F57B8E39C5D1DB1F875D57D533DB982"},
"authenticated":true,"principal":{"password":null,"username":"xi","authorities":[{"authority":"admin"},
{"authority":"user"}],"accountNonExpired":true,"accountNonLocked":true,
"credentialsNonExpired":true,"enabled":true},"credentials":null,"name":"xi"} */ //http://localhost:5500/addAuth?authName=love1
//http://localhost:5500/info }
(3)拦截位置 ,需要权限 ROLE_love1 才可以访问

3.测试

启动工程
(1)访使用一个 有 权限 ROLE_love1 的账户
username = cen
password = 11
访问网址 http://localhost:5500/home

点击登录

显然可以正常运行
访问网址 http://localhost:5500/info 查看当前登录用户的认证信息 ,是有 ROLE_love1 权限的

(2)访使用一个 没有 权限 ROLE_love1 的账户
username = yue
password = 11
访问网址 http://localhost:5500/home
选择 “记住我” ,可以自动登录

提示 403 ,

访问网址 http://localhost:5500/info 查看当前登录用户的认证信息 ,是 没有 ROLE_love1 权限的

现在添加权限
访问网址 http://localhost:5500/addAuth?authName=love1

再次 访问网址 http://localhost:5500/info 查看当前登录用户的认证信息 ,发现 有 ROLE_love1 权限了

再次 访问网址 http://localhost:5500/home ,发现访问成功啦

(2)那么现在问题来了,现在是开启了自动登录模式 ,那么关闭浏览器后 cookie是否会删除? 如果不删除 ,新加的权限是否会删除?
继续上面yue的登录页面 直接关闭浏览器,再访问 http://localhost:5500/home
发现被拦截进入 登录页面了

难道被强制登出了?
不 ,查看cookie ,并没有被删除

继续 访问 http://localhost:5500/hai ,发现是已经自动登录了

于是查看 认证信息 ,访问网址 http://localhost:5500/info

发现 ROLE_love1 权限被清除了
(3)为什么会这样?
有两个猜测 :
猜测一:在第一次登录时 ,没有权限的 认证信息已经存在cookie ,不再修改,自动登录不再从数据库获取权限信息。
猜测二 : 即便是自动登录 ,每次登录的都会从数据库获取用户信息并更新 ,以前登录时存在内存的信息会在浏览器销毁后释放。
证明:
我在注册权限的地方加了指令将添加到注册列表的权限名打印

源码
package com.example.security5500.securityConfig; import com.example.security5500.entitis.tables.TUser;
import com.example.security5500.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service; import java.util.ArrayList;
import java.util.List; @Service
public class DbUserDetailsService implements UserDetailsService { @Autowired
private UserService userService; @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//根据用户名查询用户信息
TUser tUser = userService.getByUsername(username);
if (tUser == null){
throw new UsernameNotFoundException("用户不存在!");
}
//权限设置
// List<GrantedAuthority> simpleGrantedAuthorities = new ArrayList<>();
List<SimpleGrantedAuthority> simpleGrantedAuthorities = new ArrayList<>();
String role = tUser.getRole();
//分割权限名称,如 user,admin
String[] roles = role.split(",");
System.out.println("注册该账户权限");
for (String r :roles){
System.out.println(r);
//添加权限
simpleGrantedAuthorities.add(new SimpleGrantedAuthority(r));
} // simpleGrantedAuthorities.add(new SimpleGrantedAuthority("USER"));
/**
* 创建一个用于认证的用户对象并返回,包括:用户名,密码,角色
*/
//输入参数
return new org.springframework.security.core.userdetails.User(tUser.getUsername(), tUser.getPsw(), simpleGrantedAuthorities);
} }
自动登录后
控制台打印的结果:

因此 ,猜测二是正确的 。
4.总结:
更新当前登录用户的权限列表 ,登出后将释放 ,当再次从数据库获取权限数据时将还原【包括自动登录】 ,因此如果需要持久性的更改权限,
还需要修改数据库信息
spring security 动态 修改当前登录用户的 权限的更多相关文章
- spring security中当已登录用户再次访问登录界面时,应跳转到home
@RequestMapping("/login") public String login(){ Authentication auth = SecurityContextHold ...
- Spring Security 动态url权限控制(三)
一.前言 本篇文章将讲述Spring Security 动态分配url权限,未登录权限控制,登录过后根据登录用户角色授予访问url权限 基本环境 spring-boot 2.1.8 mybatis-p ...
- Spring Security之多次登录失败后账户锁定功能的实现
在上一次写的文章中,为大家说到了如何动态的从数据库加载用户.角色.权限信息,从而实现登录验证及授权.在实际的开发过程中,我们通常会有这样的一个需求:当用户多次登录失败的时候,我们应该将账户锁定,等待一 ...
- Spring Security 入门(1-3-1)Spring Security - http元素 - 默认登录和登录定制
登录表单配置 - http 元素下的 form-login 元素是用来定义表单登录信息的.当我们什么属性都不指定的时候 Spring Security 会为我们生成一个默认的登录页面. 如果不想使用默 ...
- Spring Security OAuth2 SSO 单点登录
基于 Spring Security OAuth2 SSO 单点登录系统 SSO简介 单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自 ...
- 七:Spring Security 前后端分离登录,非法请求直接返回 JSON
Spring Security 前后端分离登录,非法请求直接返回 JSON 解决方案 在 Spring Security 中未获认证的请求默认会重定向到登录页,但是在前后端分离的登录中,这个默认行为则 ...
- Spring Security(17)——基于方法的权限控制
目录 1.1 intercept-methods定义方法权限控制 1.2 使用pointcut定义方法权限控制 1.3 使用注解定义方法权限控制 1.3.1 JSR-25 ...
- Spring Security 实战干货:图解用户是如何登录的
1. 前言 欢迎阅读Spring Security 实战干货系列文章,在集成Spring Security安全框架的时候我们最先处理的可能就是根据我们项目的实际需要来定制注册登录了,尤其是Http登录 ...
- spring security 管理会话 多个用户不可以使用同一个账号登录系统
多个用户不能使用同一个账号同时登陆系统. 1. 添加监听器 在web.xml中添加一个监听器,这个监听器会在session创建和销毁的时候通知Spring Security. <listener ...
随机推荐
- Linux centos7 安装.net 环境
其实在linux 下安装.net 环境并不复杂,但最近遇到的服务器没有外网,比较坑很多依赖都没有,记录下这次的安装过程. 一开始以为是服务器没有外网,后来发现是服务器没有配置dns,于是配置dns 第 ...
- windows下更换MySql数据库数据文件夹位置
详细解决地址 ,感谢博主 :https://blog.csdn.net/u010953266/article/details/56499361 概述 由于更换硬盘,系统重新安装了一遍,原来的mysq ...
- java多线程4:volatile关键字
上文说到了 synchronized,那么就不得不说下 volatile关键字了,它们两者经常协同处理多线程的安全问题. volatile保证可见性 那么volatile的作用是什么呢? 在jvm运行 ...
- gogs报错解决合集
目录 一.在组织中添加成员,一直显示普通用户 一.在组织中添加成员,一直显示普通用户 组织是公司,团队是公司中的不同队伍.例如A团队设置为加入就有管理员权限,那加入就有管理员. 但在组织成员那一栏中加 ...
- 虚拟机快照和linux基础命令
虚拟机快照 磁盘"快照"是虚拟机磁盘文件(VMDK)在某个点及时的副本.可以通过使用恢复到快照来保持磁盘文件和系统存储. 1.拍摄快照 拍摄快照前先关机,然后右键点击虚拟机=> ...
- CF74A Room Leader 题解
Content 一场 CF 比赛有 \(n\) 个人,有 ABCDE 五道题目.在比赛过程中,参赛者还可以随时互相攻击,成功一次加 \(100\) 分,失败一次扣 \(50\)分,已知第 \(i\) ...
- JAVA实现智能分词(通过文章标题生成tag标签)
导入jar包 IKAnalyzer2012_u6.jar下载链接:https://pan.xunlew.com/s86789 maven <dependency> <groupId& ...
- 【九度OJ】题目1185:特殊排序 解题报告
[九度OJ]题目1185:特殊排序 解题报告 标签(空格分隔): 九度OJ [LeetCode] http://ac.jobdu.com/problem.php?pid=1185 题目描述: 输入一系 ...
- 【LeetCode】1051. Height Checker 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 排序比较 日期 题目地址:https://leetc ...
- 【LeetCode】908. Smallest Range I 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 数学计算 日期 题目地址:https://leetc ...