我试图在我的网络应用中制作身份验证表单。使用自定义UserDetailsService + UserDetails。
它几乎可以工作。它适用于我尝试使用用户和我的数据库中硬编码的密码进行登录的情况。但是当我尝试与拥有加密(Bcrypt)密码的用户进行登录时,它无法正常工作......
我确定了代码的一部分是一个问题(它是Spring提供的一个类):
public class DaoAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
// [...]
@SuppressWarnings("deprecation")
protected void additionalAuthenticationChecks(UserDetails userDetails,
UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
Object salt = null;
/* ISSUE : saltSource is null */
if (this.saltSource != null) {
/* ISSUE : Moreover, my class UserDetailsImpl which implement UserDetails has no salt attribute */
salt = this.saltSource.getSalt(userDetails);
}
if (authentication.getCredentials() == null) {
logger.debug("Authentication failed: no credentials provided");
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials",
"Bad credentials"));
}
String presentedPassword = authentication.getCredentials().toString();
/* ISSUE : Has salt is null, authentication with crypted password doesn't work */
if (!passwordEncoder.isPasswordValid(userDetails.getPassword(),
presentedPassword, salt)) {
logger.debug("Authentication failed: password does not match stored value");
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials",
"Bad credentials"));
}
}
// [...]
}
此代码中没有盐。因此,当salt为null时,它会将加密的数据库密码与硬编码的浏览器密码进行比较:/。
你知道吗? THX。答案 0 :(得分:0)
盐是一些随机数据,已添加到密码中以生成唯一的哈希值,以提高安全性(What is Salt)。
if (!passwordEncoder.isPasswordValid(userDetails.getPassword(),
presentedPassword, salt))
isPasswordValid 方法根据编码的密码(userDetails.getPassword())验证指定的“原始”(presentedPassword)密码。
编码的密码以前应该已经由encodePassword(String,Object)生成。此方法将对rawPass进行编码(使用可选的salt),然后将其与显示的encPass进行比较。
这意味着盐是可选的,因此它可以为空。
在您的情况下,如果salt为null,则不会产生任何问题,如果在生成编码密码时未使用salt。只需确保在生成和保存密码时,您正在使用Spring安全密码编码api(PasswordEncoder,BCryptPasswordEncoder等)和userDetails.getPassword()返回加密的密码。
还请注意,如果您要在任何类中实现UserDetails接口,则eclipse中自动生成的getPassword方法将返回null。