高效管理用户权限:深入探索Spring Security的多用户类型认证、授权和Token刷新

前言

对于spring secutiry 来讲,其默认是只支持一种数据类型进行认证的,因为最后组件的方法仅为:loadUserByUsername(String username) 方法。

如果有多个系统来使用这个认证模块,会导致查询问题。这也就是不支持多用户类型认证的原因。

因为是多个系统,所以不同系统需要到自己的系统或者表中查询自己的数据,而单单一个参数username显然是不能满足需求的,这里至少还需一个参数来区别不同系统才行。

尽管对于不同系统可以通过增加自定义类型的方法来清醒请求access_token,即调用接口

oauth/token 来获取认证信息。

即如下:

aebea7285e224634f30bec7f23b93d1c.jpeg

但是,在使用 刷新token接口的时候,根据spring security 的机制和上面所说,还是会调用默认的loadUserByUsername 方法,导致程序报错。

这里就需要从程序的角度进行修改。这就是这里介绍的多用户数据类型的情况。

即都是刷新接口,都是调用/oauth/token接口,对应grant_type类型都是password_code类型,

对应在接口中增加一个userType即可。


刚才讲到,自定义授权类型的情况,对于兼容其他系统认证的情况,个人感觉还是不合适的,也就是为了兼容其他系统登录认证最合适的做法是稍后下面的做法,而不是增加授权类型这种这种的方式。

因为,即使获取access_token通过增加授权类型解决了,同样,刷新token还是需要更改,而2者内部其实是使用的同一套东西。

整个过程核心机制是通过接口中增加一个参数如userType来进行识别不同的系统类型,

后台逻辑中通过这个类型而进行判断。

1 登陆获取token

1.1 新增ZltUserDetailsService extends UserDetailsService,

新增自定义的方法。

因直接使用项目中内容,类方法就没有改,自定义适配的可以叫做:

CustomUserDetailsService

36a177a70039c46948713bdc84b7e2e2.jpeg

具体的实现逻辑,后续即可根据userType的值进行不同的执行逻辑:

ffd3f95f5b12a5591c18c61558392714.jpeg

需要注意:这里的userType 是接口传过来的。

后面的所有需要用到userDetailsService的,全部都要替换成自定义ZltUserDetailsService

1.2 复制org.springframework.security.authentication.dao.DaoAuthenticationProvider的代码,自定义 CustomAuthenticationProvider(注意写法,是实现AbstractUserDetailsAuthenticationProvider并将DaoAuthenticationProvider内容复制到此类里面),然后进行修改retrieveUser()方法,其他不需要动.

如下:

b48ba999bc621829f5e8158b1a83a184.jpeg

1.修改 retrieveUser 方法:

可以根据实际逻辑进行编码即可,这里是调用上面逻辑中自定义方法的逻辑:

044408f9643f67212dc8824f3a7e09ea.jpeg

2.修改成员变量:

将 UserDetailsService 变量替换成 ZltUserDetailsService

fd0abce9ba185ec7f9e6280da1253b15.jpeg

同理修改相关的get和set方法:

867443e3a25a330e380727d6135e85a1.jpeg

1.3 到WebSecurityConfigurerAdapter上配置CustomAuthenticationProvider内容。

在目前系统中是 SecurityConfig 类继承了CustomAuthenticationProvider类,故在此类中配置

需注释掉原来的内容:全局用户信息部分。

1ad74b699dc94a6f916bce429cd2132e.jpeg

同步修改成员变量:

ae4ecb7e3bb7e01c6938ca52bf8441f5.jpeg

配置完成后,可以请求接口进行

对应请求参数中增加userType即可。

01725913f368aa675bb8123d625b57a9.jpeg

2 刷新Token

对应逻辑需要同步修改,否则刷新token逻辑会调用原始loadUserByUsername

2.1 复制org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper 自定义 CustomUserDetailsByNameServiceWrapper 在 loadUserDetails() 方法添加自定义的userType

这里依然是复制整个内容,并不是继承UserDetailsByNameServiceWrapper

f422b6cb217f35d1f3aaa889621508a1.jpeg

(1)自定义loadUserDetails() 逻辑

通过相关方法,拿到userType后,即可以根据实际情况进行编码。

最后也是会调用 userDetailsService.loadUserByUsername(userName,userType);

c5719407b9fd5f11c905f83a72869045.jpeg

(2)修改成员变量

98f9b89cde435276c41af5f2900679a0.jpeg

将UserDetailsService内容改为ZltUserDetailsService

(3)同理修改构造体

c0f30379e817791fb7ccff4c4d883931.jpeg

2.2 复制 org.springframework.security.oauth2.provider.token.DefaultTokenServices 到自定义的 CustomTokenServices 然后修改refreshAccessToken() 方法

复制整个内容:

930b70c52e1c70858b70d5b0a45b8421.jpeg

修改 refreshAccessToken 方法:

其实只改了if (this.authenticationManager != null && !authentication.isClientOnly()) 这里面的内容

主要是下面内容:

91032bc576716d782e4be3821ca1cea2.jpeg

2.3 往认证服务器中配置刚刚自定义的两个类 CustomUserDetailsByNameServiceWrapper 和 CustomTokenServices。

这个可能有2种方式,一种是对应页面中展示的这种。

另一种是目前项目实现的这种方式。

2者的背后机制是一样的,因为最后都是将内容实例化后交给spring容器。

这里举例的是后者,因为是经过实际的验证通过的。个人感觉实际项目中这种方式也比较合理这种方式是依赖了自定义授权的基础。

在 TokenGranterConfig.java 类中:

实例化自定义的CustomTokenServices,创建createDefaultTokenServicesCustomer 方法

2a299a98102f23c60585e4352ac921aa.jpeg

声明CustomUserDetailsByNameServiceWrapper 类

因为这里只有声明了新增的CustomUserDetailsByNameServiceWrapper类才会调用对用的类。

1e3a66952581da2924e8790142a1ce4f.jpeg

成员变量修改

3935e59a138ff044dac95f862e59620d.jpeg

调用接口验证:

这个是在body里面:

b3681794803791833a12de03aa83c56b.jpeg

认证内容也需要配置

0354bbe772e4de480a333ffe718bb344.jpeg

配置完进行接口即可:

2b8d34741c45aecfa3ef99d8d0b1ea4e.jpeg

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

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

相关文章

Linux 虚拟内存参数配置

一、问题出发点 Jun 1 10:30:21 audit1 kernel: swapper: page allocation failure. order:1, mode:0x20 Jun 1 10:30:21 audit1 kernel: Pid: 0, comm: swapper Tainted: G --------------- T 2.6.32-431.20.3.el6.x86_64 #1 Jun 1 10:30:21 audit1 kernel: Call Trace: Jun …

Android---底层剖析 Window、Activity、View 三者关系

对于一个 Android 工程师来讲,或多或少都听说过 Window 的概念,并且隐约感受到它在 Activity 和 View 之间应该发挥着某种连接的作用。但如果要说出这三者之间的关系,多数 android 工程师都不知道从何下手。 Activity 的 setContentView Ac…

网络协议--TCP的保活定时器

23.1 引言 许多TCP/IP的初学者会很惊奇地发现可以没有任何数据流通过一个空闲的TCP连接。也就是说,如果TCP连接的双方都没有向对方发送数据,则在两个TCP模块之间不交换任何信息。例如,没有可以在其他网络协议中发现的轮询。这意味着我们可以…

墨者学院 身份认证失效漏洞实战

一、题目信息 二、漏洞利用 1.通过抓包,抓取test登录信息 发现card_id号以及一些回显的账号密码信息 搜索了一下这个id,发现是测试的头像 2.修改id号 分析请求包的逻辑,发现是请求了头像资源后再去请求头像id的详情包,所以根据…

Android NDK开发详解之Android.mk探秘

Android NDK开发详解之Android.mk探秘 概览基础知识变量和宏NDK 定义的 include 变量CLEAR_VARSBUILD_EXECUTABLEBUILD_SHARED_LIBRARYBUILD_STATIC_LIBRARYPREBUILT_SHARED_LIBRARYPREBUILT_STATIC_LIBRARY 目标信息变量TARGET_ARCHTARGET_PLATFORMTARGET_ABI 模块描述变量LOC…

leetcode第369周赛

2917. 找出数组中的 K-or 值 给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。 nums 中的 K-or 是一个满足以下条件的非负整数: 只有在 nums 中,至少存在 k 个元素的第 i 位值为 1 ,那么 K-or 中的第 i 位的值才是 1 。 返回 nums …

分享大数据分析师前景怎么样? 从事行业有哪些?

数据分析师发展前景和待遇怎么样?有前途吗?好找工作吗?根据某招聘网数据显示,当前市场表现为: 2023年较2022年同期对比增长160%,2022年较2021年下降了46%。 工资待遇:2023年较2022年下降了2…

Java 入门指南:使用 Docker 创建容器化 Spring Boot 应用程序

文章目录 步骤 1: 准备工作步骤 2: 克隆 Spring Boot 应用程序步骤 3: 创建 Dockerfile步骤 4: 构建 Docker 映像步骤 5: 运行容器步骤 6: 链接到本地数据库步骤 7: 使用 Docker Compose 运行多个容器步骤 8: 设置 CI/CD 管道结论 🎈个人主页:程序员 小侯…

Spring更加简单的读取和存储对象

前言:在上篇文章中,小编写了一个Spring的创建和使用的相关博客:Spring的创建和使用-CSDN博客,但是,操作/思路比较麻烦,那么本文主要带领大家走进:Spring更加简单的读取和存储对象! 本…

水果FL Studio21.2体验版下载安装教程(增加云服务功能)

FL Cloud 音效库包含开放版权的Loop和采样,以及来自 FL Studio 著名用户的艺术家独家内容。更新后,现在还可以使用人工智能辅助母带处理和数字发行功能来制作音轨。FL Studio 由最初的 "Fruity Loops" DAW 发展而来,25 年来&#x…

让GPT替我写vue3代码,看的我血压升高

事情是这样子的,最近在写Vue3相关的代码,就想着能不能让GPT辅助我写代码,于是,我就先写了一个中文的prompt Prompt1: 使用vue3写一个用户登录的页面 分割线内部是GPT的回答: 使用 Vue 3 来创建一个用户登录页面需要涉…

反射率检测仪如何检测后视镜

后视镜反射率检测是评估后视镜质量的重要步骤,可以反映后视镜的反射效果是否满足设计要求。一般来说,后视镜的反射率越高,驾驶员观察车后的道路状况就越清晰,从而能够更好地判断与后方车辆的距离和速度差。 后视镜反射率检测的原理…