当前位置: 首页 > news >正文

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

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> {//声明一个 providerprivate DaoAuthenticationProvider provider = new DaoAuthenticationProvider();//声明一个 UserDetailsServiceprivate 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;}@Overridepublic void configure(B builder) throws Exception {//调用后置处理器 将provider添加到SpringIoC容器中this.provider = postProcess(this.provider);// 将provider添加到builder对象中builder.authenticationProvider(this.provider);}/*** */@Overridepublic 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 GlobalAuthenticationConfigurerAdapterimplements SecurityConfigurer<AuthenticationManager, AuthenticationManagerBuilder> {@Overridepublic void init(AuthenticationManagerBuilder auth) throws Exception {}@Overridepublic void configure(AuthenticationManagerBuilder auth) throws Exception {}}

    

4、WebSecurityConfigurer

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

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

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

             

        WebSecurityConfigurer 使用示例:

               


http://www.mrgr.cn/news/25884.html

相关文章:

  • ZoneTree: 高性能ACID兼容的.NET有序键值数据库
  • 【Docker】镜像容器命令全解析
  • Linux(5)--CentOS8使用yum
  • 武汉六西格玛绿带培训多少钱
  • Apple M3编译MAVSDK安卓平台SO库
  • 10.1英寸工业三防平板提升工厂的工作效率
  • AI大模型知识点大梳理_ai大模型知识学习,零基础入门到精通,收藏这一篇就够了
  • 跑DecoupleSegNets遇到的问题
  • 关于python取四舍五入的值错误的原因
  • Zabbix监控k8s云原生环境
  • 【Qt】子控件选择器
  • node-red 资料收集
  • 大龄焦虑?老码农逆袭之路:拥抱大模型时代,焕发职业生涯新活力!
  • JAVA宠物界的Uber同城遛狗兼职系统小程序源码
  • 新教材,新挑战,家长如何助力孩子跨越英语学习的变革期
  • 企业数据质量的“谁做什么”指南
  • 谈一谈幽默的力量
  • UE5安卓项目打包安装
  • Redis——常用数据类型string
  • JavaSE:2、基本数据类型