java spring security oauth2 动态 修改当前登录用户的基础信息以及权限2.0(无需重新登录)

两年前写过一篇动态修改角色和权限当时表述的不是很全面
比如如何修改其他用户权限
修改用户信息没有效果等
再写一篇

如何修改其他用户权限

不管如何改变实际需求就是获取用户token,不管是当前用户还是所有用户
当前用户的token可以通过上下文拿到,而其他用户的token该如何拿到呢

/*** 前缀*/
String BASE_PREFIX = "base_";/*** oauth 相关前缀*/
String OAUTH_PREFIX = "oauth:";
/*** header 中Authorization*/
String AUTHORIZATION = "Authorization";
//获取当前请求token
public String getToken() {try {HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();return request.getHeader(CommonConstants.AUTHORIZATION);} catch (Exception e) {return "";}
}
//获取所有的token
private final RedisTemplate<String, Object> redisTemplate;
public Set<String> getToken() {
//获取token的前缀,不清楚的话可以去缓存redis里面找String key = String.format("%s*", SecurityConstants.BASE_PREFIX + SecurityConstants.OAUTH_PREFIX + "auth:*");ScanOptions build = ScanOptions.scanOptions().match(key).count(10000).build();return redisTemplate.execute((RedisCallback<Set<String>>) connection -> {Set<String> keysTemp = new HashSet<>();Cursor<byte[]> cursor = connection.scan(build);while (cursor.hasNext()) {keysTemp.add(new String(cursor.next()));}return keysTemp;});}

经过上述步骤就获取到了token,可以是当前请求的也可以是全部的,之后获取token的存储信息

//获取token存储
private final RedisConnectionFactory redisConnectionFactory;
public RedisTokenStore getRedisTokenStore() {RedisTokenStore tokenStore = new RedisTokenStore(redisConnectionFactory);//设置前缀 base_oauth:tokenStore.setPrefix(SecurityConstants.BASE_PREFIX + SecurityConstants.OAUTH_PREFIX);tokenStore.setAuthenticationKeyGenerator(new DefaultAuthenticationKeyGenerator() {@Overridepublic String extractKey(OAuth2Authentication authentication) {//因为设置了指定前缀return super.extractKey(authentication) + ":" + TenantContextHolder.getTenantId();}});return tokenStore;
}

拿到token的存储信息就可以通过token获取用户信息了

下面是扩展的user实体类用户信息都是用他存储的

import lombok.Getter;
import lombok.Setter;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
/*** @author 扩展用户信息*/
@Getter
public class BaseUser extends User {/*** 用户ID*/private final String id;private final String nickname;@Setterprivate Set<SysRole> sysRoleSet;@Setterprivate List<SysOrgan> sysOrganList;/*** 机构ID*/private final String organId;/*** 租户ID*/private final String tenantId;public BaseUser(String id, String organId, String tenantId, String nickname, String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);this.id = id;this.organId = organId;this.tenantId = tenantId;this.nickname = nickname;}

开始拿取用户信息并修改

public void dynamicallyUpdatePermissions() {
//tokenSet<String> execute = getToken();//token存放的地方RedisTokenStore tokenStore = getRedisTokenStore();String prefix = SecurityConstants.BASE_PREFIX + SecurityConstants.OAUTH_PREFIX + "auth:";int length = prefix.length();//将所有token循环for (String key : execute) {//拿到tokenString token = key.substring(key.indexOf(prefix) + length);//通过token获取访问令牌OAuth2AccessToken oAuth2AccessToken = tokenStore.readAccessToken(token);if (oAuth2AccessToken != null) {//获取AuthenticationOAuth2Authentication oAuth2Authentication = tokenStore.readAuthentication(oAuth2AccessToken);if (oAuth2Authentication != null) {//拿取用户信息Authentication userAuthentication = oAuth2Authentication.getUserAuthentication();Object principal = userAuthentication.getPrincipal();//当前BaseUser就是自定义userif (principal instanceof BaseUser) {BaseUser baseUser = (BaseUser) principal;//ps这里能拿到用户信息就可以去修改指定用户的信息//测试插入用户信息如 新的机构List<SysOrgan> organList = baseUser.getSysOrganList();SysOrgan sysOrgan = new SysOrgan();sysOrgan.setId("8848");sysOrgan.setName("测试");organTreeList.add(sysOrgan);baseUser.setOrganTreeList(organList );//用户信息存在于OAuth2AccessToken 的AdditionalInformation当中需要修改用户的信息就得修改它setAdditionalInformation(oAuth2AccessToken, baseUser);//下面就是修改权限
//添加权限的地方随便测试一下Set<GrantedAuthority> dbAuthsSet = new HashSet<>(userAuthentication.getAuthorities());//增加一个权限dbAuthsSet.add(new SimpleGrantedAuthority("salaryother:warningteam:testroleid"));UsernamePasswordAuthenticationToken usernamePasswordAuthentication = new UsernamePasswordAuthenticationToken(baseUser, "N_A", dbAuthsSet);usernamePasswordAuthentication.setDetails(baseUser);OAuth2Authentication oauth2Authentication = new OAuth2Authentication(oAuth2Authentication.getOAuth2Request(), usernamePasswordAuthentication);oauth2Authentication.setDetails(baseUser);//更新tokentokenStore.storeAccessToken(oAuth2AccessToken, oauth2Authentication);}}}}}
//修改AdditionalInformation ,看着来你有什么属性就加什么属性String DETAILS_USER_ID = "user_id";String DETAILS_USERNAME = "username";String NICK_USERNAME = "nickname";String ROLE_SET = "sysRoleSet";String ORGAN_TREE_LIST="sysOrganList";String DETAILS_ORGAN_ID = "organ_id";String DETAILS_TENANT_ID = "tenant_id";String DETAILS_LICENSE = "license";String BASE_LICENSE = "Copyright © 8848";
private void setAdditionalInformation(OAuth2AccessToken oAuth2AccessToken, BaseUser baseUser) {final Map<String, Object> additionalInfo = new HashMap<>(12);additionalInfo.put(SecurityConstants.DETAILS_USER_ID, baseUser.getId());additionalInfo.put(SecurityConstants.DETAILS_USERNAME, baseUser.getUsername());additionalInfo.put(SecurityConstants.DETAILS_ORGAN_ID, baseUser.getOrganId());additionalInfo.put(SecurityConstants.DETAILS_TENANT_ID, baseUser.getTenantId());additionalInfo.put(SecurityConstants.NICK_USERNAME, baseUser.getNickname());additionalInfo.put(SecurityConstants.DETAILS_LICENSE, SecurityConstants.BASE_LICENSE);additionalInfo.put(SecurityConstants.ROLE_SET, baseUser.getSysRoleSet());additionalInfo.put(SecurityConstants.ORGAN_TREE_LIST, baseUser.getSysOrganList());((DefaultOAuth2AccessToken) oAuth2AccessToken).setAdditionalInformation(additionalInfo);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/3345.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Delphi 的Show和ShowModal

Show没有返回值是一个过程&#xff0c;焦点可以不在当前窗体&#xff1b; 用法新建一个子窗体&#xff1a; 主窗体&#xff1a; 调用&#xff0c;引用子窗体的单元 调用 showmodal是一个函数有返回值&#xff0c;窗体的处理结果&#xff0c;且只能聚焦到当前窗体 效果都能展示…

尺取法知识点讲解

一、固定长度的情况&#xff1a; 最小和(sum) 输入N个数的数列&#xff0c;所有相邻的M个数的和共有N-M1个&#xff0c;求其中的最小值。 输入格式 第1行&#xff0c;2个整数N&#xff0c;M&#xff0c;范围在[3…100000]&#xff0c;N>M。 第2行&#xff0c;有N个正…

C++多线程系列——std::future | std::promise

获得线程执行任务的结果 在 C 11 之前&#xff0c;想要从线程返回执行任务的结果&#xff0c;可以通过指针来完成。 void fun(int x, int y, int* ans, std::condition_variable &cv) {// 模拟求值之前的准备工作this_thread::sleep_for(3s);*ans x y;cv.notify_one();…

monorepo mode vs standard mode使用场景和各自的优缺点

NestJS 是一个基于 TypeScript 和 Node.js 的渐进式框架&#xff0c;用于构建高效、可扩展的服务器端应用程序。在 NestJS 中&#xff0c;“monorepo”和“standard mode”分别指代两种不同的项目组织和管理方式。以下是这两种模式的优缺点对比&#xff1a; Monorepo (Monolit…

一文掌握Vue3:深度解读Vue3新特性、Vue2与Vue3核心差异以及Vue2到Vue3转型迭代迁移重点梳理与实战

每次技术革新均推动着应用性能与开发体验的提升。Vue3 的迭代进步体现在性能优化、API重构与增强型TypeScript支持等方面&#xff0c;从而实现更高效开发、更优运行表现&#xff0c;促使升级成为保持竞争力与跟进现代前端趋势的必然选择。本文深度解读Vue3 响应式数据data、生命…

基于token进行登录,每次请求携带token

一&#xff0c;什么是token&#xff1f; Token&#xff0c;也称为“令牌”&#xff0c;是服务端生成的一串字符串&#xff0c;以作客户端进行请求的一个令牌&#xff0c;当第一次登录后&#xff0c;服务器生成一个Token便将此Token返回给客户端&#xff0c;以后客户端只需带上…

蓝桥杯python考级整理

4_1:算术运算符 4_2:基本语法 4_3:基本语法 4_4:列表 4_5:函数 4_6:字符串 4_7:列表 4_8:逻辑运算符 4_9:字典 4_10:函数

MacOS通过命令行开启关闭向日葵远程控制的后台服务

categories: [Tips] tags: MacOS Tips 写在前面 经常有小伙伴问我电脑相关的问题, 而解决问题的一个重要途径就是远程了. 关于免费的远程工具我试过向日葵和 todesk, 并且主要使用向日葵, 虽然 MacOS 下要设置很多权限, 但是也不影响其丝滑的控制. 虽然用着舒服, 但是向日葵…

tcp通信协议

#include <myhead.h> #define IP "192.168.124.73" #define PORT 8888 int main(int argc, const char *argv[]) { //创建流式套接字 int sfd socket(AF_INET,SOCK_STREAM,0); if(sfd < 0){ fprintf(stderr,"line%d",__LI…

mysql的约束和表关系

根据查询的结果&#xff0c;复制出一个新表 create table newTable AS select * from oldTable; create table newPeople AS select * from day2_test.people; 约束 引入&#xff1a;如果某一列如id列&#xff0c;有重复的数据&#xff0c;无法准确定位&#xff0c;有的列有空…

实体店引流客户的最快方法是什么?线上短视频+直播引流!

前言&#xff1a;为什么想到写这个话题&#xff1f;因为在每周三晚在视频号白杨SEO免费直播的问题解答的时候&#xff0c;有个朋友问同城流量怎么做&#xff1f;我就以实体店举例解答说了做推荐搜索流量相结合。我想应该还有一些朋友也想知道&#xff0c;所以就分享出来&#x…

组合总和(Lc39)——排序+剪枝+回溯

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返回。你可以按 任意顺序 返回这些组合。 candidates 中的 同一个 数字可以 无限制重复被选取 。如…

python的练习

python 练习 一、练习题目二、代码概览 一、练习题目 Hello World 实例数字求和平方根二次方程计算三角形的面积计算圆的面积随机数生成摄氏温度转华氏温度交换变量if 语句判断字符串是否为数字判断奇数偶数判断闰年获取最大值函数质数判断输出指定范围内的素数阶乘实例九九乘…

MyBatis多参数查询解析

参考官网 1. 底层 底层是ParamNameResolver类查看getNameParams方法实现 2. 获取参数的两种方式 MyBatis获取参数值的两种方式&#xff1a; ${} : 本质就是字符串拼接#{} :本质就是占位符赋值 3. 多种情况的获取情况 单参数情况&#xff1a; a. 单参数-单个字面量类型 …

人脸清晰修复神器CodeFormer

随着AI技术在图像处理领域大展身手&#xff0c;AI去马赛克相关的项目也屡见不鲜&#xff0c;比如在Github上开源免费、备受欢迎的 CodeFormer 。不得不说利用这款神奇的人脸修复工具&#xff0c;真的是让我大开眼界&#xff0c;竟然可以这样搞&#xff01; 不管面对的是多么模…

Java知识总结-基础

Java中的访问权限修饰符 Java语言有四个权限访问修饰符&#xff0c;权限从大到小依次为&#xff1a; 1&#xff09;public &#xff1a;公共权限&#xff0c;可以被任意类访问&#xff0c;不同包不同类依然可以访问&#xff0c; 可修饰&#xff1a;类、成员变量、方法&#…

大模型+多模态实现

那么如何在预训练LLM的基础上引入跨模态的信息&#xff08;包括图像、语音、视频模态&#xff09;&#xff0c;让其变得更强大、更通用呢&#xff1f;本节将介绍“大模型多模态”的3种实现方法。 以LLM为核心&#xff0c;调用其他多模态组件 微软亚洲研究院&#xff08;MSRA&…

STM32中SPI通信的完整C语言代码范例

SPI (Serial Peripheral Interface) 是一种同步串行通信协议&#xff0c;广泛应用于嵌入式系统中&#xff0c;用于与外设进行数据交换。STM32系列微控制器提供了丰富的SPI外设&#xff0c;支持多种工作模式和配置选项。本文将以STM32F103系列为例&#xff0c;详细介绍SPI通信的…

Java基础(运算符)

运算符 运算符和表达式 运算符&#xff1a;对字面量或者变量进行操作的符号 表达式&#xff1a;用运算符把字面量或者变量连接起来&#xff0c;符合java语法的式子就可以称为表达式&#xff1b;不同运算符连接的表达式体现的是不同类型的表达式。 算术运算符&#xff08;加…

Linux基础命令[24]-su

文章目录 1. su 命令说明2. su 命令语法3. su 命令示例3.1 不加参数3.2 -&#xff08;登录&#xff09;3.3 -c&#xff08;执行命令&#xff09; 4. 总结 1. su 命令说明 su&#xff1a;以用户身份执行命令&#xff0c;基本信息如下&#xff1a; Usage:su [options] [-] [USE…