【无标题】AuthenticationManager初始化流程

前言

记录一次开发中遇到的问题,自定义了多个AuthenticationProvider,调试过程中居然找不到,发现ProviderManager的providers属性值中没有注入。经过排查,最终找到了原因,问题就出在AuthenticationManager的初始化上。自定义了多个AuthenticationProvider后,AuthenticationManager初始化出现了问题。

  1. 在Spring Security中认证功能主要由AuthenticationManager完成,但是这是一个接口,主要由其实现类ProviderManager认证完成,接下来主要介绍AuthenticationManager的创建初始化流程。
public interface AuthenticationManager {
    Authentication authenticate(Authentication var1) throws AuthenticationException;
}
  1. @EnableWebSecurity 注解, 主要看@EnableGlobalAuthentication注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({WebSecurityConfiguration.class, SpringWebMvcImportSelector.class})
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {
    boolean debug() default false;
}
  1. @EnableGlobalAuthentication,主要导入AuthenticationConfiguration这个类,重要看着一点
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({AuthenticationConfiguration.class})
@Configuration
public @interface EnableGlobalAuthentication {
}
  1. 接下来分析AuthenticationConfiguration,首先简单的了解一下过程
    AuthenticationConfiguration中收集所有GlobalAuthenticationConfigurerAdapter类型的Bean并保存到globalAuthConfigurers中;
    AuthenticationConfiguration中创建AuthenticationManagerBuilder类型的实例对象DefaultPasswordEncoderAuthenticationManagerBuilder;
    将globalAuthConfigurers里面的对象传递给AuthenticationManagerBuilder;
    执行AuthenticationManagerBuilder的build()方法完成AuthenticationManager的构建;
    WebSecurityConfigurerAdapter中调用AuthenticationConfiguration的getAuthenticationManager()方法得到构建的AuthenticationManager类似对象;
@Configuration
@Import({ObjectPostProcessorConfiguration.class})
public class AuthenticationConfiguration {
    private AtomicBoolean buildingAuthenticationManager = new AtomicBoolean();
    private ApplicationContext applicationContext;
    private AuthenticationManager authenticationManager;
    private boolean authenticationManagerInitialized;
    private List<GlobalAuthenticationConfigurerAdapter> globalAuthConfigurers = Collections.emptyList();
    private ObjectPostProcessor<Object> objectPostProcessor;

    public AuthenticationConfiguration() {
    }

    @Bean
    public AuthenticationManagerBuilder authenticationManagerBuilder(ObjectPostProcessor<Object> objectPostProcessor) {
        //构建AuthenticationManagerBuilder Bean对象
        return new AuthenticationManagerBuilder(objectPostProcessor);
    }

    @Bean
    public static GlobalAuthenticationConfigurerAdapter enableGlobalAuthenticationAutowiredConfigurer(ApplicationContext context) {
        return new EnableGlobalAuthenticationAutowiredConfigurer(context);
    }

    //初始化DaoAuthenticationProvider,UserDetailsService和PasswordEncoder(后面会详细讲)
    @Bean
    public static InitializeUserDetailsBeanManagerConfigurer initializeUserDetailsBeanManagerConfigurer(ApplicationContext context) {
        return new InitializeUserDetailsBeanManagerConfigurer(context);
    }

    //初始化AuthenticationProvider(后面会详细讲)
    @Bean
    public static InitializeAuthenticationProviderBeanManagerConfigurer initializeAuthenticationProviderBeanManagerConfigurer(ApplicationContext context) {
        return new InitializeAuthenticationProviderBeanManagerConfigurer(context);
    }

     //创建AuthenticationManager,该方法在WebSecurityConfigurerAdapter中被调用
    public AuthenticationManager getAuthenticationManager() throws Exception {
        if (this.authenticationManagerInitialized) {
            return this.authenticationManager;
        } else {
            AuthenticationManagerBuilder authBuilder = this.authenticationManagerBuilder(this.objectPostProcessor);
            if (this.buildingAuthenticationManager.getAndSet(true)) {
                return new AuthenticationManagerDelegator(authBuilder);
            } else {
                Iterator var2 = this.globalAuthConfigurers.iterator();

                while(var2.hasNext()) {
                    GlobalAuthenticationConfigurerAdapter config = (GlobalAuthenticationConfigurerAdapter)var2.next();
                    authBuilder.apply(config);
                }

                this.authenticationManager = (AuthenticationManager)authBuilder.build();
                if (this.authenticationManager == null) {
                    this.authenticationManager = this.getAuthenticationManagerBean();
                }

                this.authenticationManagerInitialized = true;
                return this.authenticationManager;
            }
        }
    }
     ==//获取GlobalAuthenticationConfigurerAdapter配置对象,后面AuthenticationManager初始化会使用到==
    @Autowired(required = false)
    public void setGlobalAuthenticationConfigurers(List<GlobalAuthenticationConfigurerAdapter> configurers) throws Exception {
        Collections.sort(configurers, AnnotationAwareOrderComparator.INSTANCE);
        this.globalAuthConfigurers = configurers;
    }
}

org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter#getHttp

    protected final HttpSecurity getHttp() throws Exception {
        if (this.http != null) {
            return this.http;
        } else {
            DefaultAuthenticationEventPublisher eventPublisher = (DefaultAuthenticationEventPublisher)this.objectPostProcessor.postProcess(new DefaultAuthenticationEventPublisher());
            this.localConfigureAuthenticationBldr.authenticationEventPublisher(eventPublisher);
            //创建AuthenticationManager,就是上面讲的在WebSecurityConfigurerAdapter中被调用
            AuthenticationManager authenticationManager = this.authenticationManager();
           this.authenticationBuilder.parentAuthenticationManager(authenticationManager);
            Map<Class<? extends Object>, Object> sharedObjects = this.createSharedObjects();
            this.http = new HttpSecurity(this.objectPostProcessor, this.authenticationBuilder, sharedObjects);
            if (!this.disableDefaults) {
                ((HttpSecurity)((DefaultLoginPageConfigurer)((HttpSecurity)((HttpSecurity)((HttpSecurity)((HttpSecurity)((HttpSecurity)((HttpSecurity)((HttpSecurity)((HttpSecurity)this.http.csrf().and()).addFilter(new WebAsyncManagerIntegrationFilter()).exceptionHandling().and()).headers().and()).sessionManagement().and()).securityContext().and()).requestCache().and()).anonymous().and()).servletApi().and()).apply(new DefaultLoginPageConfigurer())).and()).logout();
                ClassLoader classLoader = this.context.getClassLoader();
                List<AbstractHttpConfigurer> defaultHttpConfigurers = SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);
                Iterator var6 = defaultHttpConfigurers.iterator();

                while(var6.hasNext()) {
                    AbstractHttpConfigurer configurer = (AbstractHttpConfigurer)var6.next();
                    this.http.apply(configurer);
                }
            }

            this.configure(this.http);
            return this.http;
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值