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相似,而后统一由一个对象管理。

相关文章
相关标签/搜索