[英]How to use new PasswordEncoder from Spring Security
从Spring Security 3.1.4.RELEASE开始,旧的org.springframework.security.authentication.encoding.PasswordEncoder
已被弃用 ,转而使用org.springframework.security.crypto.password.PasswordEncoder
。 由于我的应用尚未向公众发布,我决定转向新的,而不是弃用的API。
到目前为止,我有一个ReflectionSaltSource
,它自动使用用户的注册日期作为每用户盐密码。
String encodedPassword = passwordEncoder.encodePassword(rawPassword, saltSource.getSalt(user));
在登录过程中,Spring还使用我的bean来验证用户是否可以登录。我无法在新密码编码器中实现这一点,因为SHA-1的默认实现 - StandardPasswordEncoder
只能添加一个编码器创建过程中的全局秘密盐。
有没有合理的方法如何使用未弃用的API进行设置?
如果您实际上没有使用现有格式注册任何用户,那么您最好切换到使用BCrypt密码编码器 。
它不那么麻烦,因为您根本不必担心盐 - 细节完全封装在编码器中。 使用BCrypt比使用普通哈希算法更强大,它也是与使用其他语言的应用程序兼容的标准。
实际上没有理由为新应用程序选择任何其他选项。
这是BCrypt的实现,它对我有用。
在spring-security.xml中
<authentication-manager >
<authentication-provider ref="authProvider"></authentication-provider>
</authentication-manager>
<beans:bean id="authProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<beans:property name="userDetailsService" ref="userDetailsServiceImpl" />
<beans:property name="passwordEncoder" ref="encoder" />
</beans:bean>
<!-- For hashing and salting user passwords -->
<beans:bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
在java类中
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String hashedPassword = passwordEncoder.encode(yourpassword);
有关弹簧安全性的更详细示例,请单击此处
希望这会有所帮助。
谢谢
我有一个类似的问题。 我需要保留旧的加密密码( Base64 / SHA-1 / Random salt Encoded ),因为用户不想更改密码或重新注册。 但是我也希望使用BCrypt编码器。
我的解决方案是编写一个定制的解码器,在匹配之前检查首先使用的加密方法( BCrypted以$
开头)。
为了解决盐问题,我通过修改后的用户对象将解密的字符串盐+加密密码传递给解码器。
解码器
@Component
public class LegacyEncoder implements PasswordEncoder {
private static final String BCRYP_TYPE = "$";
private static final PasswordEncoder BCRYPT = new BCryptPasswordEncoder();
@Override
public String encode(CharSequence rawPassword) {
return BCRYPT.encode(rawPassword);
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
if (encodedPassword.startsWith(BCRYP_TYPE)) {
return BCRYPT.matches(rawPassword, encodedPassword);
}
return sha1SaltMatch(rawPassword, encodedPassword);
}
@SneakyThrows
private boolean sha1SaltMatch(CharSequence rawPassword, String encodedPassword) {
String[] saltHash = encodedPassword.split(User.SPLIT_CHAR);
// Legacy code from old system
byte[] b64salt = Base64.getDecoder().decode(saltHash[0].getBytes());
byte[] validHash = Base64.getDecoder().decode(saltHash[1]);
byte[] checkHash = Utility.getHash(5, rawPassword.toString(), b64salt);
return Arrays.equals(checkHash, validHash);
}
}
用户对象
public class User implements UserDetails {
public static final String SPLIT_CHAR = ":";
@Id
@Column(name = "user_id", nullable = false)
private Integer userId;
@Column(nullable = false, length = 60)
private String password;
@Column(nullable = true, length = 32)
private String salt;
。
。
@PostLoad
private void init() {
username = emailAddress; //To comply with UserDetails
password = salt == null ? password : salt + SPLIT_CHAR + password;
}
您还可以添加一个钩子,以新的BCrypt格式重新编码密码并替换它。 因此逐步淘汰旧方法。
刚刚在互联网上阅读了这篇文章以及Spring中的选项,我得到了第二个Luke的答案,使用BCrypt(它在Spring的源代码中提到)。
我发现解释为什么哈希/盐和为什么使用BCrypt的最佳资源是一个很好的选择在这里: 盐渍密码哈希 - 做得对 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.