将多个Spring安全身份验证提供程序组合到自定义单一服

时间:2017-12-07 13:34:28

标签: spring-security spring-java-config

我的目标是使用凭据进行两步验证。第一步是检查具有主体的用户是否在特殊数据库表中具有角色。第二是执行标准的ldap认证。

我需要的是同时执行两个检查,但与身份验证提供程序的一种常见方法是在任何身份验证提供程序首次成功后声明身份验证成功。因此,我决定创建一个自定义AuthenticationProvider实现,该实现调用LdapAuthenticationProvider,然后执行数据库检查逻辑,但它没有工作,因为没有什么可以使用AbstractLdapAuthenticationProvider进行自动装配。

请告诉我是否

  1. 解决此类问题的方法是理性的
  2. 如果它是合理的,我怎么能注入AbstractLdapAuthenticationProvider?
  3. 安全配置代码

    @Autowired
    private DBRoleAuthenticationProvider dbRoleAuthenticationProvider;
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.ldapAuthentication()
                .contextSource()
                .url("...")
                .managerDn("...")
                .managerPassword("...")
                .and()
                .userSearchFilter("uid={0}");
        auth.authenticationProvider(dbRoleAuthenticationProvider);
    }
    

    自定义身份验证提供程序

    @Component
    public class DBRoleAuthenticationProvider implements AuthenticationProvider {
    
        @Autowired
        private UserHasRoleInDBService userHasRoleInDBService;
    
        @Autowired
        private AbstractLdapAuthenticationProvider ldapAuthenticationProvider;
    
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            authentication = ldapAuthenticationProvider.authenticate(authentication);
            if (!authentication.isAuthenticated()) {
                return authentication;
            }
            try {
                String loginToSearch = (String) authentication.getPrincipal();
                if (!userHasRoleInDBService.userHasRole(loginToSearch)) {
                    authentication.setAuthenticated(false);
                }
            } catch (Exception e) {
                authentication.setAuthenticated(false);
            }
            return authentication;
        }
    
        @Override
        public boolean supports(Class<?> authentication) {
            return authentication.equals(UsernamePasswordAuthenticationToken.class);
        }
    }
    

    提前致谢!

1 个答案:

答案 0 :(得分:0)

看起来像auth.authenticationProvider(dbRoleAuthenticationProvider); 正在击败auth.ldapAuthentication()

您应该通过查看doc的文档来自定义为经过身份验证的用户检索权限的方式 userDetailsContextMapper(UserDetailsContextMapper userDetailsContextMapper) and ldapAuthoritiesPopulator(LdapAuthoritiesPopulator ldapAuthoritiesPopulator) LdapAuthenticationProviderConfigurer