当前位置: 首页 > 知识库问答 >
问题:

使用AuthenticationManagerBuilder的提供程序顺序

东方建修
2023-03-14

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

我希望使用AuthenticationManagerBuilder,因为这就是<code>WebSecurityConfigurerAdapter。configureGlobal()公开,但我看不到任何指定顺序的方法。我需要手动创建ProviderManager吗?

更新:这是基于Arun的答案的问题澄清。我想使用的特定提供程序是用于自定义UserServiceActiveDirectoryLdapAuthenticationProviderDaoAuthenticationProvider

最终,我想首先针对Dao Auth的提供程序进行身份验证,然后针对ActiveDirectoryLdapAuth的提供程序进行身份验证。

AD 提供程序涉及对 AuthenticationManagerBuilder.authenticationProvider() 的调用,但 DAO 提供程序涉及调用 AuthenticationManagerBuilder.userService(),这会在幕后围绕用户服务创建 DaoAuthenticationProvider查看源代码,它不会直接将提供程序放在提供程序列表中(它创建了一个配置器),因此 Arun 的答案在这里对我不起作用。

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

共有3个答案

葛骏
2023-03-14

我在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"));
    }    
}
池俊茂
2023-03-14

没有明确的订购条款。调用的顺序将是您向AuthenticationManagerBuilder.AuthenticationProvider()提供AuthentiationProvider

例如

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

将导致以下调用顺序

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

将导致以下顺序的调用身份验证提供者1,身份验证提供者2

刘海
2023-03-14

我在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;
        }
    });
}

这是在您的WebSecurityCon的继承类上的配置方法。

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

希望有帮助…如果你有任何问题,请告诉我。

 类似资料:
  • 我使用的是Spring Boot 2.0(利用Spring Security 5.0)。我正在尝试向WebSecurityConfigureAdapter子类中的AuthenticationManager添加自定义AuthenticationProvider。如果我重写configure(AuthenticationManagerBuilder)方法来提供我的新提供者,那么我不知道如何将Authe

  • 我已经创建了身份提供程序,并且从浏览器中它工作正常。 参考:密钥斗篷身份提供程序后代理登录抛出错误 从浏览器,我可以使用外部IDP登录,如果外部IDP用户不在keycloak中,它会在keyclock中创建,这绝对没问题,并重定向到仪表板。 但我的问题是,我们如何用keycloak rest api实现这个流程? 是否有任何api用于使用外部IDP登录,并将获得外部IDP的令牌以及密钥斗篷的令牌?

  • 我正在使用pact-jvm提供程序Spring。我有两个不同的pact(.json)文件,比如(order.json和irs.json),我需要按顺序运行它们(order后面是irs),但是根据字母顺序选择测试类,irs首先运行,order其次运行。是否有方法调用、执行特定的测试类提供程序状态或定义测试类执行顺序?

  • 本文向大家介绍F# 使用CSV类型提供程序,包括了F# 使用CSV类型提供程序的使用技巧和注意事项,需要的朋友参考一下 示例 给定以下CSV文件: 您可以使用以下脚本读取数据:            

  • 我正在尝试使用pact来验证spring boot微服务。我已经从consumer生成了pact文件,并在provider端使用pact Broker验证了它。 我有另一个用例,在根据实际的服务响应验证pact文件之前,我需要执行一些代码。我读过关于状态改变URL和状态改变与闭包来实现它,但没有得到一个如何实现这一点的例子。有人能帮忙吗? 如果这个客户不存在,那么我将需要通过读取pact文件中的更

  • 我已经在文件中添加了所有相关build.gradle依赖项。尽管如此,当我尝试运行调用SOAP服务时,还是会出现以下错误。共享依赖项部分和错误详细信息。使用Java11。网上已经有很多答案,但似乎都不起作用。任何帮助/建议将是值得赞赏的。 低于错误跟踪