SpringSecurity原理解析(六):SecurityConfigurer 解析

news2024/11/16 22:55:37

1、SecurityConfigurer

     SecurityConfigurer 在 Spring Security 中是一个非常重要的接口,观察HttpSecurity 中的很多

     方法可以发现,SpringSecurity 中的每一个过滤器都是通过 xxxConfigurer 来进行配置的,而

     这些 xxxConfigurer 其实都是 SecurityConfigurer  的实现。

     SecurityConfigurer 是一个接口,其定义如下:

public interface SecurityConfigurer<O, B extends SecurityBuilder<O>> {

	/**
	 * Initialize the {@link SecurityBuilder}. Here only shared state should be created
	 * and modified, but not properties on the {@link SecurityBuilder} used for building
	 * the object. This ensures that the {@link #configure(SecurityBuilder)} method uses
	 * the correct shared objects when building. Configurers should be applied here.
	 * @param builder
	 * @throws Exception
     *
     * 初始化 SecurityBuilder
	 */
	void init(B builder) throws Exception;

	/**
	 * Configure the {@link SecurityBuilder} by setting the necessary properties on the
	 * {@link SecurityBuilder}.
	 * @param builder
	 * @throws Exception
     *
     * 通过设置必要的属性来配置 SecurityBuilder
	 */
	void configure(B builder) throws Exception;

}

     由 SecurityConfigurer 定义可以发现 init方法和 configure方法的参数都是 SecurityBuilder 的类

     型,而SecurityBuilder是用来构建过滤器链 DefaultSecurityFilterChainProxy的,从前边

     的笔记可以知道 DefaultSecurityFilterChainProxy 是 SecurityConfigurer  的是实现类

     AbstractConfiguredSecurityBuilder中构建的。

     SecurityConfigurer 的实现有很多,但我们只需要关注其中三个核心实现,即:

          SecurityConfigurerAdapter

          GlobalAuthenticationConfigurerAdapter 

           WebSecurityConfigurer

     

2、SecurityConfigurerAdapter

      SecurityConfigurerAdapter 是 SecurityConfigurer 的基础实现类(抽象类),并没有实现

      接口 SecurityConfigurer 的方法,而是在SecurityConfigurer 的基础上扩展了几个方法;

      在SpringSecurity 中很多xxxConfigurer也是 SecurityConfigurerAdapter 的子类。

2.1、SecurityConfigurerAdapter 核心属性

        SecurityConfigurerAdapter 核心属性只有2个,一个是 SecurityBuilder 类型 另一个是 

       CompositeObjectPostProcessor,如下图所示:

               

       其中 CompositeObjectPostProcessor 是 SecurityConfigurerAdapter 的一个内部类,并实现

       了接口 ObjectPostProcessor,ObjectPostProcessor 是一个后置处理器,

        ObjectPostProcessor只有2个实现,即 AutowireBeanFactoryObjectPostProcessor 和

        CompositeObjectPostProcessor;

        1)AutowireBeanFactoryObjectPostProcessor :

              该类主要功能是通过 AutowireCapableBeanFactory 将指定的bean对象注册到spring容器

               中,通过前边HttpSecurity 中的方法可以窥见一斑,SpringSecurity 中的对象很多都是直

               接new 出来的,这些new手动创建的对象需要手动注册到spring容器中后,在其他地方才

              能访问;AutowireBeanFactoryObjectPostProcessor 就是用来将这些new 出来的对象注

              册到spring容器的。如下图所示:

                      

                      

        2)CompositeObjectPostProcessor

              CompositeObjectPostProcessor 则是一个复合的对象处理器,里边维护了一个 List 集

              合,这个List 集合中,大部分情况下只存储一条数据,那就是

              AutowireBeanFactoryObjectPostProcessor(因为 ObjectPostProcessor 就2个实现,除

              了CompositeObjectPostProcessor 自身,剩下的只有

               AutowireBeanFactoryObjectPostProcessor ),用来完成对象注入到容器的操作;

                         

2.2、SecurityConfigurerAdapter 常用方法

2.2.1、addObjectPostProcessor

            若用户手动调用了该方法,那么CompositeObjectPostProcessor 集合中维护的数据就会增

            加一条,CompositeObjectPostProcessor.postProcess 方法中,会遍历集合中的所有

             ObjectPostProcessor,挨个调用其 postProcess 方法对对象进行后置处理。

public void addObjectPostProcessor(ObjectPostProcessor<?> objectPostProcessor) {
		this.objectPostProcessor.addObjectPostProcessor(objectPostProcessor);
	}

2.2.2、add()

            该方法返回值是一个 securityBuilder,这里securityBuilder 实际上就是 HttpSecurity,我们

            在HttpSecurity 中去配置不同的过滤器时,可以使用 and 方法进行链式配置,就是因为这

            里定义了 and 方法并返回了 securityBuilder 实例

public B and() {
		return getBuilder();
	}

	
	protected final B getBuilder() {
		Assert.state(this.securityBuilder != null, "securityBuilder cannot be null");
		return this.securityBuilder;
	}

2.3、SecurityConfigurerAdapter 核心子类

         SecurityConfigurerAdapter 的主要子类也是有个,即:    

                   1)UserDetailsAwareConfigurer

                   2) AbstractHttpConfigurer

                   3)LdapAuthenticationProviderConfigurer

          由于 LDAP 现在使用很少,所以这里重点介绍下前两个      

2.3.1、UserDetailsAwareConfigurer

            UserDetailsAwareConfigurer是用户配置相关的类,定义如下:

                   

public abstract class UserDetailsAwareConfigurer<B extends ProviderManagerBuilder<B>, U extends UserDetailsService>
		extends SecurityConfigurerAdapter<AuthenticationManager, B> {

	/**
     * 返回的是UserDetailsService 接口的实现
	 * Gets the {@link UserDetailsService} or null if it is not available
	 * @return the {@link UserDetailsService} or null if it is not available
	 */
	public abstract U getUserDetailsService();

}

            通过定义我们可以看到泛型U必须是UserDetailsService接口的实现,也就是
            getUserDetailsService()方法返回的肯定是UserDetailsService接口的实现,还有通

            过泛型B及继承SecurityConfigurerAdapter来看,UserDetailsAwareConfigurer类中应该

           会构建一个AuthenticationManager对象。

2.3.1.1、AbstractDaoAuthenticationConfigurer

              UserDetailsAwareConfigurer 只有一个子类,即 AbstractDaoAuthenticationConfigurer;

              AbstractDaoAuthenticationConfigurer 类的主要用于配置DaoAuthenticationProvider;

              AbstractDaoAuthenticationConfigurer 类定义如下:

// B--ProviderManagerBuilder
// C--AbstractDaoAuthenticationConfigurer
// U--UserDetailsService
public abstract class AbstractDaoAuthenticationConfigurer<B extends ProviderManagerBuilder<B>, C extends AbstractDaoAuthenticationConfigurer<B, C, U>, U extends UserDetailsService>
		extends UserDetailsAwareConfigurer<B, U> {
     
    //声明一个 provider
	private DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
    //声明一个 UserDetailsService
	private final U userDetailsService;

	/**
	 * 传递的对象可以是UserDetailsService或者UserDetailsPasswordService
	 */
	AbstractDaoAuthenticationConfigurer(U userDetailsService) {
		this.userDetailsService = userDetailsService;
		this.provider.setUserDetailsService(userDetailsService);
		if (userDetailsService instanceof UserDetailsPasswordService) {
			this.provider.setUserDetailsPasswordService((UserDetailsPasswordService) userDetailsService);
		}
	}

	/**
	 * 添加了一个ObjectPostProcessor 后置处理器
	 */
	@SuppressWarnings("unchecked")
	public C withObjectPostProcessor(ObjectPostProcessor<?> objectPostProcessor) {
		addObjectPostProcessor(objectPostProcessor);
		return (C) this;
	}

	/**
	 * 添加密码编码器 用于加密
	 */
	@SuppressWarnings("unchecked")
	public C passwordEncoder(PasswordEncoder passwordEncoder) {
		this.provider.setPasswordEncoder(passwordEncoder);
		return (C) this;
	}

	public C userDetailsPasswordManager(UserDetailsPasswordService passwordManager) {
		this.provider.setUserDetailsPasswordService(passwordManager);
		return (C) this;
	}

	@Override
	public void configure(B builder) throws Exception {
        //调用后置处理器 将provider添加到SpringIoC容器中
		this.provider = postProcess(this.provider);
        // 将provider添加到builder对象中
		builder.authenticationProvider(this.provider);
	}

	/**
	 * 
	 */
	@Override
	public U getUserDetailsService() {
		return this.userDetailsService;
	}

}

            AbstractDaoAuthenticationConfigurer 也只有一个子类,即UserDetailsServiceConfigurer

            UserDetailsServiceConfigurer

                    该类的功能是用于在AuthenticationManagerBuilder中配置UserDetailsService。 

                    该类实现的核心是在 configure 方法执行之前加入了 initUserDetailsService 方

                    法,以方便开发展按照自己的方式去初始化 UserDetailsService;

                    在 UserDetailsServiceConfigurer 中 initUserDetailsService 是抽象方法,由子类

                    去实现,如下图所示:

                                    

              UserDetailsManagerConfigurer类:

                    UserDetailsManagerConfigurer是 UserDetailsServiceConfigurer 的子类,

                    UserDetailsManagerConfigurer 中实现了 UserDetailsServiceConfigurer 中定义的

                     initUserDetailsService 方法,具体的实现逻辑就是将 UserDetailsBuilder 所构建出

                     来的 UserDetails 以及提前准备好的 UserDetails 中的用户存储到 UserDetailsService

                     中。

                     该类同时添加了 withUser 方法用来添加用户,同时还增加了一个 UserDetailsBuilder

                     用来构建用 户。

                     UserDetailsManagerConfigurer 有2个子类,分别是:   

                              JdbcUserDetailsManagerConfigurer   

                              InMemoryUserDetailsManagerConfigurer     

             JdbcUserDetailsManagerConfigurer类:

                      JdbcUserDetailsManagerConfigurer 在父类的基础上补充了 DataSource 对象,

                      同时还提供了相应 的数据库查询方法

             InMemoryUserDetailsManagerConfigurer类:

                       InMemoryUserDetailsManagerConfigurer 在父类的基础上重写了构造方法,

                       将父类中的 UserDetailsService 实例定义为 InMemoryUserDetailsManager,

                       如下所示:      

public class InMemoryUserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>>
		extends UserDetailsManagerConfigurer<B, InMemoryUserDetailsManagerConfigurer<B>> {

	/**
	 * Creates a new instance
	 */
	public InMemoryUserDetailsManagerConfigurer() {
		super(new InMemoryUserDetailsManager(new ArrayList<>()));
	}

}

              

2.3.2、AbstractHttpConfigurer

                   

           AbstractHttpConfigurer是 在HttpSecurity上运行的SecurityConfigurer实例 的基类;也

           就是说 HttpSecurity 上运行的 SecurityConfigurer 都是 AbstractHttpConfigurer 的子类。

           AbstractHttpConfigurer  子类有很多,SpringSecurity 中的过滤器配置类都继承

           了 AbstractHttpConfigurer,如: FormLoginConfigurer、DefaultLoginPageConfigurer

            和 CsrfConfigurer 等等。

           AbstractHttpConfigurer 继承于SecurityConfigurerAdapter,并扩展了2个方法,

           AbstractHttpConfigurer 定义如下:

                 

public abstract class AbstractHttpConfigurer<T extends AbstractHttpConfigurer<T, B>, B extends HttpSecurityBuilder<B>>
		extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, B> {

	/**
	 * getBuilder 中移除相关的 xxxConfigurer,
     * getBuilder 方法获取到的实际上就是 HttpSecurity,所以移除掉 xxxConfigurer 实际上就是从过滤器链中移除掉某一个过滤器
	 */
	@SuppressWarnings("unchecked")
	public B disable() {
		getBuilder().removeConfigurer(getClass());
		return getBuilder();
	}

    /**
     *为配置类添加手动添加后置处理器,返回值是当前配置类,
     *
     * 该方法常用于链式配置上
     *
     */
	@SuppressWarnings("unchecked")
	public T withObjectPostProcessor(ObjectPostProcessor<?> objectPostProcessor) {
		addObjectPostProcessor(objectPostProcessor);
		return (T) this;
	}

}

3、GlobalAuthenticationConfigurerAdapter    

     GlobalAuthenticationConfigurerAdapter 是一个全局的配置类,使用该类对应的Bean 对象可以

     用来配置全局的 AuthenticationManagerBuilder;

     GlobalAuthenticationConfigurerAdapter 实现了 SecurityConfigurerAdapter 接口,但是并未对

     方法做具体的实现,只是将泛型具体化了

      GlobalAuthenticationConfigurerAdapter 定义如下:

@Order(100)
public abstract class GlobalAuthenticationConfigurerAdapter
		implements SecurityConfigurer<AuthenticationManager, AuthenticationManagerBuilder> {

	@Override
	public void init(AuthenticationManagerBuilder auth) throws Exception {
	}

	@Override
	public void configure(AuthenticationManagerBuilder auth) throws Exception {
	}

}

    

4、WebSecurityConfigurer

      WebSecurityConfigurer 只有一个实现,即 WebSecurityConfigurerAdapter;当我们自定义

      SpringSecurity 配置时,需要继承类 WebSecurityConfigurerAdapter;

      所以这里 WebSecurityConfigurer 功能就很明确了,即用户扩展用户自定义的配置。

             

        WebSecurityConfigurer 使用示例:

               

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

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

相关文章

针对Docker容器的可视化管理工具—DockerUI

目录 ⛳️推荐 前言 1. 安装部署DockerUI 2. 安装cpolar内网穿透 3. 配置DockerUI公网访问地址 4. 公网远程访问DockerUI 5. 固定DockerUI公网地址 ⛳️推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下…

GBI(生成式商业智能)实际业务生产落地运用上的探索和实践

前言 最近在探索如何发展AI在业务上的驱动力时了解到了生成式商业智能这一概念&#xff0c;同时本人也在探索ChatBI这一技术的实际落地运用&#xff0c;其实二者几乎在实现效果层面是一个意思&#xff0c;GBI(Generative Business Intelligence)是偏向业务方面&#xff0c;而C…

[000-01-008].第05节:OpenFeign高级特性-超时控制

我的后端学习大纲 SpringCloud学习大纲 1.1.OpenFeign超时的情况&#xff1a; 在Spring Cloud微服务架构中&#xff0c;大部分公司都是利用OpenFeign进行服务间的调用&#xff0c;而比较简单的业务使用默认配置是不会有多大问题的&#xff0c;但是如果是业务比较复杂&#xff…

UiBot教程:实现复杂流程图的高效方法

在自动化测试和RPA&#xff08;机器人流程自动化&#xff09;领域&#xff0c;使用UiBot绘制复杂流程图是日常工作中常见的挑战之一。如何在繁杂的逻辑中保持高效&#xff1f;如何实现复杂流程的自动化设计而不迷失于其中&#xff1f;这是许多测试工程师和自动化开发者所面临的…

区块链之变:揭秘Web3对互联网的改变

传统游戏中&#xff0c;玩家的虚拟资产&#xff08;如角色、装备&#xff09;通常由游戏公司控制&#xff0c;玩家无法真正拥有这些资产或进行交易。而在区块链游戏中&#xff0c;虚拟资产通过去中心化技术记录在区块链上&#xff0c;玩家对其拥有完全的所有权&#xff0c;并能…

Loki 分布式日志中心服务

目录 Loki 是什么 Loki 配置文件介绍 Loki 安装 Promtail 配置文件介绍 Promtail 安装 Loki 整合 Grafana Loki 是什么 Loki 是一个专为日志聚合和查询设计的开源分布式日志管理系统&#xff0c;由 Grafana Labs 开发。它与 Prometheus 类似&#xff0c;但用于处理日志&a…

决策树实战

文章目录 一、入门基础案例二、基于sklearn的决策树模型2.1sklearn中的决策树实现2.2分类型决策树&#xff1a;DecisionTreeClassifier2.2.1重要参数2.2.2重要属性与接口2.2.3基本案例&#xff1a;wine葡萄酒数据集 2.3回归型决策树&#xff1a;DecisionTreeRegressor2.3.1重要…

大学选修课无人机航拍技术与技巧怎么样?

在当今这个视觉盛行的时代&#xff0c;无人机航拍技术以其独特的视角和非凡的创意能力&#xff0c;正逐步成为影视制作、新闻报道、地理测绘、环境监测及个人记录生活等领域不可或缺的工具。为此&#xff0c;本大学特设《无人机航拍技术与技巧》选修课&#xff0c;旨在通过系统…

Linux数据相关-第3个服务-实时同步sersync

1、实时同步 背景&#xff1a; 之前我们通过rsync 定时任务实现定时备份/同步对于NFS我们需要进行实时同步 选择 分布式存储.。使用实时同步服务NFS。选择公有云对象存储&#xff0c;七牛存储&#xff0c;腾讯存储COS 选择&#xff1a;nfs实时同步工具 inotify(bug需要书…

3D点云目标检测数据集标注工具 保姆级教程——CVAT (附json转kitti代码)

前言&#xff1a; 笔者尝试过很多3D标注软件都遇到很多问题&#xff0c;例如CloudCompare不适合做3D目标检测的数据集而且分割地面的时很繁琐&#xff1b;labelCloud没有三视图&#xff0c;视角难以调整标得不够精确&#xff1b;SUSTechPOINTS换帧麻烦、输出时存储在docker里面…

每日OJ_牛客_数字统计(简单模拟)

目录 牛客_数字统计&#xff08;简单模拟&#xff09; 解析代码 牛客_数字统计&#xff08;简单模拟&#xff09; [NOIP2010]数字统计_牛客题霸_牛客网 描述 请统计某个给定范围[L, R]的所有整数中&#xff0c;数字2出现的次数。 比如给定范围[2, 22]&#xff0c;数字2在数…

sipp模拟uas发送reinvite

概述 freeswitch是一款简单好用的VOIP开源软交换平台。 在更新了sipp模拟update的配置方案之后&#xff0c;我希望对比一下fs对update和reinvite的处理流程。 本文档记录sipp的配置方案&#xff0c;该方案中包含了update和reinvite的信令。 环境 CentOS 7.9 freeswitch 1…

Linux入门攻坚——32、Mini Linux制作

制作一个mini linux&#xff0c;需要对linux的启动流程很熟悉&#xff0c;这里又一次学习Linux的启动过程。 启动流程&#xff1a;CentOS 6 / 5&#xff1a; POST -->BootSequence(BIOS) --> BootLoader --> kernel (ramdisk) --> rootfs --> /sbin/init …

MySQL——数据类型(二)

目录 一、日期与时间类型 1.1 date 1.2 datetime 1.3 timestamp 二、枚举和联合 2.1 enum 2.2 set 2.2.1 set 的插入 2.2.2 set 的查找 思维导图可以参考如下链接&#xff1a; 数据类型.xmind 夜夜亮晶晶/MySQL - Gitee.com 一、日期与时间类型 1.1 date 日期 yyy…

2024 年最佳 Chrome 验证码扩展,解决 reCAPTCHA 问题

验证码&#xff0c;特别是 reCAPTCHA&#xff0c;已成为在线安全的不可或缺的一部分。虽然它们在区分人类和机器人方面起着至关重要的作用&#xff0c;但它们也可能成为合法用户和从事网络自动化的企业的主要障碍。无论您是试图简化在线体验的个人&#xff0c;还是依赖自动化工…

easy-es动态索引支持

背景 很多项目目前都引入了es&#xff0c;由于es弥补了mysql存储及搜索查询的局限性&#xff0c;随着技术的不断迭代&#xff0c;原生的es客户端使用比较繁琐不直观&#xff0c;上手代价有点大&#xff0c;所以easy-es框架就面世了&#xff0c;学习成本很低&#xff0c;有空大…

Ubuntu下安装最新版本Apache2文件服务器

文章目录 1.最新版本Apache2安装2. Apache2配置2.1 端口配置2.2 创建软连接,生成文件服务2.3 隐藏Apache2服务版本号2.4 添加用户&#xff0c;设置Apache2文件服务密码2.5 重启Apache2服务3. 执行后效果 1.最新版本Apache2安装 注意&#xff1a;安装最新版本必须升级Ubuntu为20…

Linux 中System V IPC的共享内存

1. 概念介绍 System V IPC&#xff08;Inter-Process Communication&#xff09;是一组在UNIX系统中用于进程间通信的机制&#xff0c;包括共享内存、消息队列和信号量。这些机制由System V内核提供&#xff0c;并且它们的存在不依赖于创建它们的进程&#xff0c;而是由内核管…

JSON数组

数组作为JSON对象 ["Google","Runoob","Taobao"] JSON数组在中括号中书写。 中括号[]保存的数组是值&#xff08;value&#xff09;的有序集合。一个数组以左中括号[开始&#xff0c;右中括号]结束&#xff0c;值之间使用逗号&#xff0c;分隔…

【第28章】Spring Cloud之Sentinel注解支持

文章目录 前言一、注解埋点支持二、SentinelResource 注解三、实战1. 准备2. 纯资源定义3. 添加资源配置 四、熔断(fallback)1. 业务代码1.1 Controller1.2 Service1.3 ServiceImpl 2. 熔断配置3. 熔断测试 总结 前言 上一章我们已经完成了对Sentinel的适配工作&#xff0c;这…