【问题标题】:Spring Boot - Authentication via local DB or Active Directory depending on flagSpring Boot - 根据标志通过本地数据库或 Active Directory 进行身份验证
【发布时间】:2019-05-30 04:45:41
【问题描述】:

我前段时间开发了一个 Spring Boot 应用程序,并使用本地数据库进行用户身份验证。

现在,由于应用程序的使用越来越多,我也想通过我公司的活动目录启用身份验证。

我仍然希望将所有用户保留在我的本地用户表中,以便从其他表中引用它们,但要针对某些用户的活动目录检查用户名和密码。用户是活动目录用户还是本地用户都保存在用户表中。

在伪代码中它看起来像这样:

if(user.isAdUser()) {
    checkCredentialsAgainstAD();
} else {
    checkCredentialsAgainstLocalDb();
}

我当前的验证码如下所示:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDAO userDao;

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

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(new CustomUserDetailsService(userDao)).passwordEncoder(new BCryptPasswordEncoder());
    }
}

并通过覆盖的loadUserByUsername(String username)方法中的userDao从数据库中加载用户信息:

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User user = userDao.readUserByLogin(username, true);

    if(user == null){
        log.info(username + " not found");
        throw new UsernameNotFoundException(username + " not found");
    }

    User userObj = user.clone();
    userObj.password = null;

    return new CustomUserDetails(user.loginName, user.password, getAuthorities(user), userObj);
}

我已经想出可以像这样添加ActiveDirectoryLdapAuthenticationProvider

@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(new ActiveDirectoryLdapAuthenticationProvider("DOMAIN", "ldap://example.com")).userDetailsService(new CustomUserDetailsService(userDao)).passwordEncoder(new BCryptPasswordEncoder());
})

但那总是使用活动目录。

如何具体选择要使用的身份验证提供程序?

我不想按照Java Spring Security config - multiple authentication providers 中建议的顺序测试所有提供程序,但只测试正确的一个,这取决于我从数据库中获取的标志。

【问题讨论】:

  • "每个身份验证提供程序都按顺序进行测试。"不是我想做的。
  • 我认为您必须定义您的自定义 AuthenticationProvider 并使用 ActiveDirectoryLdapAuthenticationProvider 的实例作为委托。
  • 你怎么知道你的用户是AdUser?用户来自哪里?

标签: java spring-boot authentication active-directory


【解决方案1】:

根据您的要求,我认为最简单的解决方案可能是创建您的自定义AuthenticationProvider,它在内部包装DaoAuthenticationProviderActiveDirectoryLdapAuthenticationProvider

只有这个自定义 AuthenticationProvider 将被注册。在身份验证期间,您首先从 DB 获取用户以确定他们的“身份验证模式”并相应地委托给 DaoAuthenticationProviderActiveDirectoryLdapAuthenticationProvider 以进行进一步的身份验证。

如下所示,欢迎修改:

@Service
public class MyCustomAuthenticationProvider implements AuthenticationProvider{

        @Autowired
        private DaoAuthenticationProvider dbAuthProvider;

        @Autowired
        private ActiveDirectoryLdapAuthenticationProvider adAuthProvider;

        @Autowired
        UserDAO userDao;

        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException{

            // Determine username
            String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED": authentication.getName();
            User user = userDao.getUserByName(username);
            if(user == null){
                throw new  AuthenticationException("Sorry. No this user.");
            }

            if(user.isAdUser()) {
                return adAuthProvider.authenticate(authentication);
            } else {
               return dbAuthProvider.authenticate(authentication);
            }

        }

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


}

但是如何通过注释配置来连接它们是另一个需要跟进的故事.....

【讨论】:

    猜你喜欢
    • 2017-12-29
    • 2020-07-06
    • 2020-02-16
    • 1970-01-01
    • 2017-04-06
    • 2012-03-02
    • 1970-01-01
    • 2011-12-04
    • 1970-01-01
    相关资源
    最近更新 更多