首页 > 解决方案 > 连接多种认证机制 Spring Boot Security

问题描述

我的应用程序有一个安全配置,通过LDAP. 这工作得很好,但现在我想添加另一个AuthenticationProvider对尝试进行身份验证的用户进行更多检查。所以我尝试添加一个DbAuthenticationProvider(用于测试目的)总是拒绝访问。因此,当我尝试使用我的域帐户(适用于activeDirectoryLdapAuthenticationProvider)登录时,我无法访问该页面,因为第二个提供商未通过身份验证。

为了实现这个目标,我使用了以下代码:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Value("${ad.domain}")
    private String AD_DOMAIN;

    @Value("${ad.url}")
    private String AD_URL;

    @Autowired
    UserRoleComponent userRoleComponent;

    @Autowired
    DbAuthenticationProvider dbAuthenticationProvider;

    private final Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class);

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        this.logger.info("Verify logging level");
        http.authorizeRequests().anyRequest().fullyAuthenticated().and().formLogin()
                .successHandler(new CustomAuthenticationSuccessHandler()).and().httpBasic().and().logout()
                .logoutUrl("/logout").invalidateHttpSession(true).deleteCookies("JSESSIONID");
        http.formLogin().defaultSuccessUrl("/", true);
    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
        auth.authenticationProvider(dbAuthenticationProvider);
    }

    @Bean
    public AuthenticationManager authenticationManager() {
        return new ProviderManager(Arrays.asList(activeDirectoryLdapAuthenticationProvider(), dbAuthenticationProvider));
    }

    @Bean
    public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
        ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(AD_DOMAIN,
                AD_URL);
        provider.setConvertSubErrorCodesToExceptions(true);
        provider.setUseAuthenticationRequestCredentials(true);
        return provider;
    }
}

这是我的DbAuthenticationProvider

@Component
public class DbAuthenticationProvider implements AuthenticationProvider {

    Logger logger = LoggerFactory.getLogger(DbAuthenticationProvider.class);

    @Override
    public Authentication authenticate(Authentication auth) throws AuthenticationException {
        auth.setAuthenticated(false);
        this.logger.info("Got initialized");
        return auth;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return true;
    }

}

可悲的是,我能够登录(访问没有像我预期的那样被拒绝)。我错过了什么吗?

标签: springspring-bootauthenticationspring-security

解决方案


Spring 不会使用多个AuthenticationProvider来验证请求,因此支持对象并成功验证请求的第一个(在 中ArrayList)将是唯一使用的。在你的情况下,它是.AuthenticationProviderAuthenticationactiveDirectoryLdapAuthenticationProvider

ActiveDirectoryLdapAuthenticationProvider您可以使用委托给 LDAP 并进行额外检查的自定义 AuthenticationProvider而不是使用:

    CustomerAuthenticationProvider implements AuthenticationProvider{
        privtae ActiveDirectoryLdapAuthenticationProvider  delegate; // add additional methods to initialize delegate during your configuration

          @Override
         public Authentication authenticate(Authentication auth) throws 
             AuthenticationException {
            Authentication  authentication= delegate.authenticate(auth);
            additionalChecks(authentication);
           return auth;
           }


          @Override
          public boolean supports(Class<?> authentication) {
            return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
          }

        public void additionalCheck(Authentication authentication){
               // throw AuthenticationException when it's not allowed
        }

    }

推荐阅读