Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/388.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring引导-通过本地DB或Active Directory进行身份验证,具体取决于标志_Java_Spring Boot_Authentication_Active Directory - Fatal编程技术网

Java Spring引导-通过本地DB或Active Directory进行身份验证,具体取决于标志

Java Spring引导-通过本地DB或Active Directory进行身份验证,具体取决于标志,java,spring-boot,authentication,active-directory,Java,Spring Boot,Authentication,Active Directory,我不久前开发了一个Spring引导应用程序,并使用本地数据库进行用户身份验证 现在,由于应用程序的使用越来越多,我还想通过我公司的active directory启用身份验证 我仍然希望保留本地用户表中的所有用户,以便从其他表中引用它们,但对于某些用户,请对照active directory检查用户名和密码。用户是和active directory用户还是本地用户都保留在用户表中 在伪代码中,它看起来像这样: if(user.isAdUser()) { checkCredentialsA

我不久前开发了一个Spring引导应用程序,并使用本地数据库进行用户身份验证

现在,由于应用程序的使用越来越多,我还想通过我公司的active directory启用身份验证

我仍然希望保留本地用户表中的所有用户,以便从其他表中引用它们,但对于某些用户,请对照active directory检查用户名和密码。用户是和active directory用户还是本地用户都保留在用户表中

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

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());
    }
}
我当前的身份验证代码如下所示:

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(字符串用户名)
方法中的
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());
})
但这将始终使用active directory

如何具体选择将使用哪个身份验证提供商?


我不想按照中建议的顺序测试所有提供者,但只测试正确的提供者,这取决于我从数据库中获得的标志。

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

只有此自定义的
AuthenticationProvider
将被注册。在身份验证过程中,您首先从DB获取用户以确定其“身份验证模式”,并相应地委托给
DAAuthenticationProvider
ActiveDirectoryLdapAuthenticationProvider
,以进行进一步的身份验证

如下图所示,请随意修改:

@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);
        }


}
@服务
公共类MyCustomAuthenticationProvider实现AuthenticationProvider{
@自动连线
私有DaoAuthenticationProvider dbAuthProvider;
@自动连线
私有ActiveDirectoryLdapAuthenticationProvider ADAuthenticationProvider;
@自动连线
UserDAO UserDAO;
@凌驾
公共身份验证(身份验证)引发AuthenticationException{
//确定用户名
字符串用户名=(authentication.getPrincipal()==null)?“未提供”:authentication.getName();
User=userDao.getUserByName(用户名);
if(user==null){
抛出新的AuthenticationException(“对不起,没有此用户”);
}
if(user.isAdUser()){
返回adAuthProvider.authenticate(身份验证);
}否则{
返回dbAuthProvider.authenticate(身份验证);
}
}
@凌驾
公共布尔支持(类身份验证){
返回UsernamePasswordAuthenticationToken.class.isAssignableFrom(身份验证);
}
}

但如何通过带注释的配置连接它们是另一个需要跟进的问题。…

可能重复“每个身份验证提供程序都按顺序进行测试”这不是我想做的。我认为您必须定义自定义AuthenticationProvider,并使用ActiveDirectoryLdapAuthenticationProvider的实例作为委托。您如何知道您的用户是Duser?用户来自哪里?