springsecurity 配置認證信息

在以前的文章中咱們提到了WebSecurityConfigurerAdapter中的兩個web

configure(WebSecurity web)
configure(HttpSecurity http)app

然而還有一個很是重要的configure方法,咱們在繼承WebSecurityConfigurerAdapter時能夠經過覆蓋下面這個configure來配置認證信息ide

configure(AuthenticationManagerBuilder auth)函數

其實這個configure的套路與configure(HttpSecurity http)相似,也是經過對它的參數進行配置,至於怎麼配置就是調用AuthenticationManagerBuilder裏的方法,他的方法也大都會註冊一個configurer,而後又是會調用到以下的方法:post

protected final O doBuild() throws Exception {
        synchronized (configurers) {
            buildState = BuildState.INITIALIZING;

            beforeInit();
            init();

            buildState = BuildState.CONFIGURING;

            beforeConfigure();
            configure();

            buildState = BuildState.BUILDING;

            O result = performBuild();

            buildState = BuildState.BUILT;

            return result;
        }
    }ui

這個和以前的configure(HttpSecurity http)套路同樣。只是這個是配置AuthenticationManagerBuilder,那個是配置HttpSecurity,或者說AuthenticationManagerBuilder維護了一組認證信息,HttpSecurity維護了一組filter。this


咱們先看performBuild()方法:spa

在AuthenticationManagerBuilder類中debug

protected ProviderManager performBuild() throws Exception {
        if (!isConfigured()) {
            logger.debug("No authenticationProviders and no parentAuthenticationManager defined. Returning null.");
            return null;
        }
        ProviderManager providerManager = new ProviderManager(authenticationProviders,
                parentAuthenticationManager);
        if (eraseCredentials != null) {
            providerManager.setEraseCredentialsAfterAuthentication(eraseCredentials);
        }
        if (eventPublisher != null) {
            providerManager.setAuthenticationEventPublisher(eventPublisher);
        }
        providerManager = postProcess(providerManager);
        return providerManager;
    }
orm

他最終返回了一個providerManager,有什麼用先不說,咱們能夠看到關鍵的參數authenticationProviders,從名字來看,providerManager是用來維護authenticationProviders的。那authenticationProviders是怎麼來的呢,想一想就知道應該是咱們調用了AuthenticationManagerBuilder裏的某些配置方法註冊了某些configurer,而後在上面那個doBuild裏的configure();中依次調用這些configurer裏的configure方法建立了authenticationProvider,而後把它加入到authenticationProviders中。

舉個例子:咱們有時會繼承WebSecurityConfigurerAdapter而後覆蓋他的configure(AuthenticationManagerBuilder auth)方法,以下:

  public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
        .inMemoryAuthentication()
             .withUser("root")
                  .password("root")
                  .roles("USER");
    }

public InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> inMemoryAuthentication()
            throws Exception {
        return apply(new InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder>());
    }

咱們能夠看到InMemoryUserDetailsManagerConfigurer是個configurer,apply就是把configurer註冊到AuthenticationManagerBuilder維護的configurers,nMemoryAuthentication()返回InMemoryUserDetailsManagerConfigurer對象,繼續調用withUser等方法就是爲了建立一個UserDetailsBuilder對象()裏面包括用戶名,密碼,角色之類的信息),而後放入UserDetailsManagerConfigurer中的userBuilders

而後等上面那個doBuild()裏調用configure();時,InMemoryUserDetailsManagerConfigurer這個configurer中的configure方法會被調用,也就是 UserDetailsServiceConfigurer中的  

public void configure(B builder) throws Exception {
        initUserDetailsService();

        super.configure(builder);
    }

protected void initUserDetailsService() throws Exception {
        for (UserDetailsBuilder userBuilder : userBuilders) {
            getUserDetailsService().createUser(userBuilder.build());
        }
    }

這裏能夠看到把以前的userBuilders裏的全部userBuilder放入userDetailsService的實現類中來維護,對應InMemoryUserDetailsManagerConfigurer他的userDetailsService的實現類是InMemoryUserDetailsManager。接着看那個super.configure(builder);

public void configure(B builder) throws Exception {
        provider = postProcess(provider);
        builder.authenticationProvider(provider);
    }

這個builder就是AuthenticationManagerBuilder類型,provider是以下類型:

private DaoAuthenticationProvider provider = new DaoAuthenticationProvider();

由AbstractDaoAuthenticationConfigurer中的初始化函數可知provider用來維護userDetailsService,也就是說每套用戶認證信息都會被放到userDetailsService中維護,而後這個provider維護這個userDetailsService。

protected AbstractDaoAuthenticationConfigurer(U userDetailsService) {
        this.userDetailsService = userDetailsService;
        provider.setUserDetailsService(userDetailsService);
    }

而後繼續前面那個configure

public void configure(B builder) throws Exception {
        provider = postProcess(provider);
        builder.authenticationProvider(provider);
    }

public AuthenticationManagerBuilder authenticationProvider(
            AuthenticationProvider authenticationProvider) {
        this.authenticationProviders.add(authenticationProvider);
        return this;
    }

能夠看到這裏真正把Provider放到了authenticationProviders(開篇提到的那個authenticationProviders),因此能夠看出,AuthenticationManagerBuilder裏configurers中的每一個configurer都能生成一個Provider,就像HttpSecurity中的每一個configurer都能生成一個filter相似,而後統一由一個對象管理。

相關文章
相關標籤/搜索