我正在将 Spring 安全性从 4.2.16.RELEASE
迁移到 5.6.3
版本。现有的项目安全配置使用已弃用的 ShaPasswordEncoder
和自定义 SaltSource
来生成 salt。 salt 由应用程序配置属性和用户的 uuid 组成:
<bean id="customAuthenticationProvider" class="com.my.security.CustomUserDetailsAuthenticationProvider">
<property name="userDetailsService" ref="CustomUserDetailsService" />
<property name="saltSource" ref="saltSource" />
<property name="passwordEncoder" ref="passwordEncoder" />
<property name="servicesURL" value="${custom.services.url}" />
</bean>
<bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder">
<constructor-arg value="256" />
</bean>
<bean id="saltSource" class="com.my.security.UserSaltSource">
<property name="userPropertyToUse" value="CustomId" />
<property name="systemWideSalt" value="${security.systemwide.salt}" />
</bean>
getSalt
方法:
public Object getSalt(String secondSaltProperty) {
try {
return secondSaltProperty + this.systemWideSalt;
} catch (Exception exception) {
throw new AuthenticationServiceException(exception.getMessage(),
exception);
}
}
我的目标不仅是迁移到更新的 Spring 安全版本,而且还开始使用推荐的 BCryptPasswordEncoder
密码编码器。根据https://docs.spring.io/spring-security/site/docs/5.0.0.RC1/api/org/springframework/security/crypto/password/MessageDigestPasswordEncoder.html,我必须迁移现有密码:
该格式旨在与 Spring 安全核心模块中的 DigestPasswordEncoder 一起使用。但是,需要迁移密码以在密码中包含任何盐,因为此 API 在内部提供盐,而不是使其成为用户的责任。要从 SaltSource 迁移密码,请使用以下命令: String salt = saltSource.getSalt(user);字符串 s = salt == null ?空:“{”+盐+“}”; String migratedPassword = s + user.getPassword();
问题:关于密码迁移部分我不清楚的是结合了新的密码存储格式{id}encodedPassword
,其中id
用于选择相应的密码编码器,以及salt部分。根据 https://spring.io/blog/2017/11/01/spring-security-5-0-0-rc1-released#password-storage-format 我必须在存储的密码中添加 {sha256}
前缀,因此 DelegatingPasswordEncoder
会选择正确的解码器,但是如何处理 salt
部分呢?
我的理解如下:首先我必须定义 DelegatingPasswordEncoder
并且如果我不将 id
前缀添加到密码中,我必须使用 DelegatingPasswordEncoder.setDefaultPasswordEncoderForMatches
方法设置默认密码编码器以获取旧密码编码器.接下来,在自定义的AuthenticationProvider
服务类中实现认证逻辑,在其中注入passwordEncoder
用于密码匹配检查。在调用 PasswordEncoder.matches(CharSequence rawPassword, String encodedPassword);
之前,我必须添加将格式化编码密码以匹配 {salt}password
格式的代码。
下一步是添加成功的身份验证侦听器,它将重新编码密码以匹配 {bcrypt}password
格式并将 store 格式输入 DB。因此,在下一次用户登录尝试时,将调用 BCryptPasswordEncoder
密码编码器。
迁移所有密码后,我将能够删除自定义 SaltSource-wise 内容和成功的身份验证侦听器。
如果我错了或者我遗漏了什么,请纠正我。谢谢。
回答1
您只需要做两件事。
- 迁移密码以在模式
{salt}<password-hash>
中包含盐 - 配置
DelegatingPasswordEncoder
并将正确配置的MessageDigestPasswordEncoder
设置为默认值。因此,如果没有指定编码,它将回退到那个编码。
如果您想即时转换密码,您可以使用 succes 处理程序执行此操作并更新记录以使用 BCrypt/SCrypt 而不是您现在拥有的。