我不久前开发了一个 Spring Boot 应用程序,并使用本地数据库进行用户身份验证。
现在,由于该应用程序的使用越来越多,我还想通过我公司的 Activity 目录启用身份验证。
我仍然希望将所有用户保留在本地用户表中,以便从其他表中引用它们,但根据某些用户的 Activity 目录检查用户名和密码。用户是 Activity 目录用户还是本地用户都保存在用户表中。
在伪代码中,它看起来像这样:
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());
})
但这将始终使用 Activity 目录。
我如何具体选择要使用的身份验证提供程序?
我不想按照 Java Spring Security config - multiple authentication providers 中建议的顺序测试所有提供程序但只有正确的一个,具体取决于我从数据库中获取的标志。
最佳答案
根据您的要求,我认为最简单的解决方案可能是创建自定义的AuthenticationProvider
,它在内部包装DaoAuthenticationProvider
和ActiveDirectoryLdapAuthenticationProvider
。
只有这个自定义的AuthenticationProvider
会被注册。在身份验证期间,您首先从数据库获取用户以确定他们的“身份验证模式”并委托(delegate)给DaoAuthenticationProvider
或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);
}
}
但是如何通过带注释的配置来连接它们是另一个需要跟进的故事......
关于java - Spring Boot - 根据标志通过本地数据库或 Active Directory 进行身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54024928/