Spring security 是否可以使用两种不同的AuthenticationProvider';使用WebSecurityConfigureAdapter的是什么?

Spring security 是否可以使用两种不同的AuthenticationProvider';使用WebSecurityConfigureAdapter的是什么?,spring-security,spring-security-kerberos,Spring Security,Spring Security Kerberos,我有一个基于SpringBoot的应用程序,有多个端点。由于将访问端点的客户端不同,我希望有不同的身份验证提供程序来保护它们。某些端点将受到Kerberos(KerberosServiceAuthenticationProvider--)的保护。某些端点将受到AD/LDAP(ActiveDirectoryLdapAuthenticationProvider)的保护 我目前使用Kerberos或LDAP,但不能同时使用: @Order(SecurityProperties.ACCESS_OVERR

我有一个基于SpringBoot的应用程序,有多个端点。由于将访问端点的客户端不同,我希望有不同的身份验证提供程序来保护它们。某些端点将受到Kerberos(KerberosServiceAuthenticationProvider--)的保护。某些端点将受到AD/LDAP(ActiveDirectoryLdapAuthenticationProvider)的保护

我目前使用Kerberos或LDAP,但不能同时使用:

@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
protected class ApplicationSecurity extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

//For Kerberos
        auth.authenticationProvider(kerberosAuthenticationProvider())
            .authenticationProvider(kerberosServiceAuthenticationProvider());
//For LDAP  
        //auth.authenticationProvider(customAuthenticationProvider());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
            http
                .authorizeRequests()
                    .antMatchers(HttpMethod.GET, APPLICATION_ADMIN_ENDPOINTS)
                    .permitAll()
                    .and()
                .authorizeRequests()
                    .antMatchers(HttpMethod.PUT, APPLICATION_ADMIN_ENDPOINTS)
                    .hasAnyAuthority(AUTHENTICATED_APPLICATION_ADMIN_AUTHORITIES)
                    .and()
                .authorizeRequests()
                    .antMatchers(HttpMethod.DELETE, APPLICATION_ADMIN_ENDPOINTS)
                    .hasAnyAuthority(AUTHENTICATED_APPLICATION_ADMIN_AUTHORITIES)
                    .and()
                .authorizeRequests()
                    .antMatchers(CLIENT_ENDPOINTS)
                    .permitAll()
                    .and()
                .authorizeRequests()
                    .antMatchers(SWAGGER_ENDPOINTS)
                    .permitAll()
                    .and()
                .authorizeRequests()
                    .antMatchers(MANAGER_ENDPOINTS)
                    .hasAnyAuthority(AUTHENTICATED_MANAGER_AUTHORITIES)
                    .and()
                .authorizeRequests()
                    .antMatchers(TRUSTED_AGENT_ENDPOINTS)
                    .hasAnyAuthority(AUTHENTICATED_TRUSTED_AGENT_AUTHORITIES)
                    .and()
                .authorizeRequests()
                    .antMatchers("/kerb/**")
                    .hasAnyAuthority(AUTHENTICATED_APPLICATION_ADMIN_AUTHORITIES)
                    .and()
                .addFilterBefore(spnegoAuthenticationProcessingFilter(authenticationManagerBean()), BasicAuthenticationFilter.class)
                .httpBasic()
                    .and()
                .csrf()
                    .disable();
    }
}

@Bean
public AuthenticationProvider customAuthenticationProvider() {
    ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(
            ldapDomain, ldapUrl);
    SimpleCaseAndWhitespaceMitigatingAuthoritiesMapper authoritiesMapper = new SimpleCaseAndWhitespaceMitigatingAuthoritiesMapper();
    provider.setAuthoritiesMapper(authoritiesMapper);
    provider.setConvertSubErrorCodesToExceptions(true);
    return provider;
}

@Bean
public KerberosAuthenticationProvider kerberosAuthenticationProvider() {
    KerberosAuthenticationProvider provider = new KerberosAuthenticationProvider();
    SunJaasKerberosClient client = new SunJaasKerberosClient();
    client.setDebug(true);
    provider.setKerberosClient(client);
    provider.setUserDetailsService(kerberosUserService());
    return provider;
}

@Bean
public KerberosServiceAuthenticationProvider kerberosServiceAuthenticationProvider() {
    KerberosServiceAuthenticationProvider provider = new KerberosServiceAuthenticationProvider();
    provider.setTicketValidator(sunJaasKerberosTicketValidator());
    provider.setUserDetailsService(kerberosUserService());
    return provider;
}

@Bean
public SunJaasKerberosTicketValidator sunJaasKerberosTicketValidator() {
    SunJaasKerberosTicketValidator ticketValidator = new SunJaasKerberosTicketValidator();
    ticketValidator.setServicePrincipal(kerberosPrincipal);
    File f = new File(keytabFile);
    try {
        LOG.info(String.format("Absolute: %s, Canonical: %s", f.getAbsolutePath(), f.getCanonicalPath()));
        if(f.exists()){
            LOG.info("File exists.");
        }
        else{
            LOG.info("File DOES NOT exist.");
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    ticketValidator.setKeyTabLocation(new FileSystemResource(f));
    ticketValidator.setDebug(true);
    return ticketValidator;
}

@Bean
public SpnegoAuthenticationProcessingFilter spnegoAuthenticationProcessingFilter(AuthenticationManager authenticationManager) {
    SpnegoAuthenticationProcessingFilter filter = new SpnegoAuthenticationProcessingFilter();
    filter.setAuthenticationManager(authenticationManager);
    return filter;
}

@Bean
public KerberosUserDetailsService kerberosUserService() {
    return new KerberosUserDetailsService();
}

为了让这两个都能用?我正在考虑创建一个自定义的身份验证提供程序来处理请求,但不确定它是否有效。

最简单的方法是基于url映射在Web.xml中创建SpringDispatcherServlets。然后,每个url映射都位于不同的spring上下文中。然后,每个spring上下文都可以有自己的安全性。

您所做的是为Kerberos添加
身份验证提供程序
,并将您的自定义提供程序添加到
身份验证管理器构建器
。这应该登记所有这些人

 public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(kerberosAuthenticationProvider());
auth.authenticationProvider(kerberosServiceAuthenticationProvider());
    auth.authenticationProvider(customAuthenticationProvider());
}
运行时发生的情况:

有一个
ProviderManager
处理您所有注册的
AuthenticationProvider
和内置的

  • 首先,它尝试作为匿名用户进行身份验证。如果请求的URL设置为
    permitAll
    ,则故事到此结束
  • 然后,
    ProviderManager
    按照您提供的顺序迭代所有的
    AuthenticationProvider
    。它检查它们是否支持身份验证,并尝试使用它们进行身份验证。如果失败,则移动到下一个异常(如果存在异常,则保存异常)
  • 最后还有一个
    DaoAuthenticationProvider
    处理普通用户名密码凭据
  • 如果任何提供程序成功,则用户将登录,否则将引发保存的异常
结论: 你所做的应该很接近,如果不是你想要的。对于受Kerberos保护的端点,它将使用Kerberos
AuthenticationProvider
。对于其他端点,它将尝试使用Kerberos并失败,然后转到您的自定义提供程序


如果有些东西仍然不起作用,我建议在类
org.springframework.security.authentication.ProviderManager中设置一个断点,看看它是如何处理您的提供者的。

您到底想做什么?是否有一些端点使用kerberos,其他端点使用自定义AD身份验证,或者在所有端点上都使用kerberos和自定义AD身份验证?同时使用两者时,您遇到了什么错误,例如,
authenticationProvider(kerberosAuthenticationProvider()).authenticationProvider(kerberosServiceAuthenticationProvider()).authenticationProvider(customAuthenticationProvider())欢迎使用堆栈溢出。请复习。加上一个简短的解释就好了。