使用AuthenticationManagerBuilder的提供者订单

时间:2015-07-08 19:44:02

标签: java spring authentication spring-security

我使用的是Spring Security 4.0.1,并希望使用多个身份验证提供程序进行基于Java配置的身份验证。如何指定提供者订单?

我希望使用AuthenticationManagerBuilder,因为WebSecurityConfigurerAdapter.configureGlobal()暴露了什么,但我没有看到任何指定顺序的方法。我是否需要手动创建ProviderManager

更新:根据Arun的回答,这是一个问题澄清。对于自定义ActiveDirectoryLdapAuthenticationProvider,我要使用的特定提供商为DaoAuthenticationProviderUserService

最终,我想首先针对DaoAuthenticationProviderActiveDirectoryLdapAuthenticationProvider秒进行身份验证。

AD提供商涉及对AuthenticationManagerBuilder.authenticationProvider()的调用,但DAO提供商涉及调用AuthenticationManagerBuilder.userService(),这会在幕后的用户服务周围创建DaoAuthenticationProvider。查看源代码,它并没有直接将提供者放在提供者列表中(它创建了一个配置器),所以Arun的答案在这里不适合我。

我尝试手动创建DaoAuthenticationProvider并将其传递给authenticationProvider()。它没有影响订单。

3 个答案:

答案 0 :(得分:1)

没有明确的订购条款。调用顺序将是您将AuthenticationProvider提供给AuthenticationManagerBuilder.authenticationProvider()的顺序。有关xml配置,请参阅handling SMS messages。同样适用于java配置。

例如

auth.authenticationProvider(getAuthenticationProvider2());
auth.authenticationProvider(getAuthenticationProvider1());

将导致以下调用顺序AuthenticationProvider2,AuthenticationProvider1

 auth.authenticationProvider(getAuthenticationProvider1());
 auth.authenticationProvider(getAuthenticationProvider2());

将导致以下调用顺序AuthenticationProvider1,AuthenticationProvider2

答案 1 :(得分:1)

我在configure方法中尝试了一个objectPostProcessor并且它工作正常。不确定这是否是你想要的:

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
      auth.jdbcAuthentication().dataSource(dataSource)
           .passwordEncoder(new BCryptPasswordEncoder());
      auth.authenticationProvider(new CustomAuthenticationProvider(this.dataSource));

      auth.objectPostProcessor(new ObjectPostProcessor<Object>() {
        @Override
        public <O> O postProcess(O object) {
            ProviderManager providerManager = (ProviderManager) object;
            Collections.swap(providerManager.getProviders(), 0, 1);
            return object;
        }
    });
}

这是继续 WebSecurityConfigurerAdapter 继承类的 configure 方法。

对象后处理器的原因是我们需要等待AuthenticationManagerBuilder实际构建对象,然后才能访问和更改提供者列表的顺序。

希望它有所帮助..如果您有任何问题,请告诉我。

答案 2 :(得分:0)

我在Spring 5应用程序中遇到了完全相同的问题,但是对于我来说,创建DaoAuthenticationProvider很有帮助。这是我的代码(我省略了很多代码,并粘贴了最重要的代码)。

...
import javax.annotation.PostConstruct;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@Import(SecurityProblemSupport.class)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    private final Logger log = LoggerFactory.getLogger(SecurityConfiguration.class);

    private final AuthenticationManagerBuilder authenticationManagerBuilder;

    private final UserDetailsService userDetailsService;

    private final TokenProvider tokenProvider;

    private final CorsFilter corsFilter;

    private final SecurityProblemSupport problemSupport;

    public SecurityConfiguration(AuthenticationManagerBuilder authenticationManagerBuilder, UserDetailsService userDetailsService, TokenProvider tokenProvider, CorsFilter corsFilter, SecurityProblemSupport problemSupport) {
        this.authenticationManagerBuilder = authenticationManagerBuilder;
        this.userDetailsService = userDetailsService;
        this.tokenProvider = tokenProvider;
        this.corsFilter = corsFilter;
        this.problemSupport = problemSupport;
    }

    @PostConstruct
    public void init() {
        try {
            authenticationManagerBuilder.authenticationProvider(userDetailsAuthenticationProvider());

            if (isSsoEnabled()) {
                authenticationManagerBuilder
                    .authenticationProvider(activeDirectoryLdapAuthenticationProvider());
            }

            if (isKerberosEnabled()) {
                authenticationManagerBuilder
                    .authenticationProvider(kerberosServiceAuthenticationProvider());
            }

        } catch (Exception e) {
            throw new BeanInitializationException("Security configuration failed", e);
        }
    }

    @Bean
    public DaoAuthenticationProvider userDetailsAuthenticationProvider() {
        DaoAuthenticationProvider authProvider
            = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userDetailsService);
        authProvider.setPasswordEncoder(passwordEncoder());
        return authProvider;
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new CustomPasswordEncoder();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        ...
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
    ...
    }

    private JWTConfigurer securityConfigurerAdapter() {
        return new JWTConfigurer(tokenProvider);
    }

    private ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
        ActiveDirectoryLdapAuthenticationProvider provider =
            new ActiveDirectoryLdapAuthenticationProvider(getAdDomain(), getAdServer());
        provider.setUserDetailsContextMapper((UserDetailsContextMapper) userDetailsService);
        return provider;
    }


    private boolean isSsoEnabled() {
        return Boolean.parseBoolean(ConfigurationFileUtils.getConfigurationProperty("security.use-sso"));
    }

    private boolean isKerberosEnabled() {
        return isSsoEnabled() && Boolean.parseBoolean(ConfigurationFileUtils.getConfigurationProperty("security.use-kerberos"));
    }    
}