我已经使用spring boot实现了OAuth 2.0 . 我将散列密码(包括盐)存储到我的数据库中 .
我是Spring的新手,无法弄清楚如何验证用户名/密码 .
这是我的UserDAO类:
@Service
public class UserDAO implements UserDetailsService{
@Autowired
private LoginDetailsManager loginDetailsManager;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println("Get user");
LoginDetails user = loginDetailsManager.getByUsername(username);
System.out.println(user.toString());
if (user == null) {
// Not found...
throw new UsernameNotFoundException(
"User " + username + " not found.");
}
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_USER");
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
grantedAuthorities.add(grantedAuthority);
String password = user.getPasswordHash();
String salt = user.getSalt();
return new UserDetailsImpl(
user.getUsername(),
user.getPasswordHash(),
salt,
grantedAuthorities);
}
}
这是Application类的安全配置器:
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.allowFormAuthenticationForClients();
}
问题:
-
如何检索用户输入的密码? UserDetailsService的实现为我提供了用户输入的用户名 .
-
是否有内置方法来处理此"hashed password+salt"身份验证?我弄错了吗?
2 回答
在Spring Security中,检索主体,提供分别匹配密码的salt和编码都是相互分离的 . 您的UserDetails服务基本上是获取主体的正确方法 .
你必须提供一个PasswordEncoder,Spring Boot中的默认值是BCrypt,它与你的哈希值不匹配 . Spring Boot和Spring Security不再使用旧密码编码器(ShaPasswordEncoder等)以及salt源 . 您必须手动定义它们 .
这个配置应该基本上做你想要的,因为你有一个包含盐列的
UserDetails
. 如果您从我即将出版的书中完整实施ShaPasswordEncoderConfig.java .为了使这项工作,您必须为自己的UserDetails实现角色,而不是使用Spring Security本身的那个,因为它没有存储salt的属性 .
我在示例中使用的
SaltSource
是一个lambda,它将UserDetails
强制转换为我的实现并获取盐 . 您也可以使用ReflectionSaltSource
这是一个通过反射获取salt的实现 .Edit
UserDetails
易于实现,请参阅:你可以使用这样的实现:
我最终实现了自己的
PasswordEncoder
接口,并使用本地静态变量将salt传递给db .根据我对控制流程的观察,实施是实验性的:
PasswordEncoder中的
客户端密钥验证
如果清除了步骤1,则在userDAO中
loadUserByUsername
.PasswordEncoder中的密码验证
在我的UserDAO中,我从持久性中获取用户详细信息,我会在返回用户之前将salt存储到对象常量中: