将 Spring 安全性 4.x(ShaPasswordEncoder 和每个用户的唯一盐)迁移到 5.x(BCryptPasswordEncoder)
Migrate Spring Security 4.x (ShaPasswordEncoder and unique salt for each user) to 5.x (BCryptPasswordEncoder)
我正在将 Spring 安全性从 4.2.16.RELEASE
版本迁移到 5.6.3
版本。
现有的项目安全配置使用已弃用的 ShaPasswordEncoder
和自定义的 SaltSource
生成盐。 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
密码编码器。
根据migration guide,我必须迁移现有密码:
The format is intended to work with the DigestPasswordEncoder that was found in the Spring Security core module. However, the passwords will need to be migrated to include any salt with the password since this API provides Salt internally vs making it the responsibility of the user. To migrate passwords from the SaltSource use the following:
String salt = saltSource.getSalt(user);
String s = salt == null ? null : "{" + salt + "}";
String migratedPassword = s + user.getPassword();
问题: 密码迁移部分我不清楚的是结合了新的密码存储格式{id}encodedPassword
,其中使用了id
用于选择相应的密码编码器和盐部分。
根据 migration guide 我必须在存储的密码中添加 {sha256}
前缀,因此 DelegatingPasswordEncoder
将选择正确的解码器,但是如何处理 salt
部分呢?
我的理解如下:
首先,我必须定义 DelegatingPasswordEncoder
,如果我不在密码中添加 id
前缀,我必须使用 DelegatingPasswordEncoder.setDefaultPasswordEncoderForMatches
方法设置默认密码编码器以获取旧密码编码器.
接下来,在自定义AuthenticationProvider
服务class中实现认证逻辑,其中注入passwordEncoder
用于密码匹配校验。在调用 PasswordEncoder.matches(CharSequence rawPassword, String encodedPassword);
之前,我必须添加将格式化编码密码以匹配 {salt}password
格式的代码。
下一步是添加成功的身份验证侦听器,它将重新编码密码以匹配 {bcrypt}password
格式并将其存储到数据库中。因此,在下次用户登录尝试时,将改为调用 BCryptPasswordEncoder
密码编码器。
迁移所有密码后,我将能够删除自定义的 SaltSource-wise 内容和成功的身份验证侦听器。
如果我错了或者遗漏了什么,请纠正我。谢谢。
您只需要做两件事。
- 迁移密码以在模式中包含盐
{salt}<password-hash>
- 配置
DelegatingPasswordEncoder
并将正确配置的 MessageDigestPasswordEncoder
设置为默认值。因此,如果未指定编码,它将回退到那个编码。
如果您想即时转换密码,您可以使用成功处理程序并更新记录以使用 BCrypt/SCrypt 而不是您现在拥有的内容。
我正在将 Spring 安全性从 4.2.16.RELEASE
版本迁移到 5.6.3
版本。
现有的项目安全配置使用已弃用的 ShaPasswordEncoder
和自定义的 SaltSource
生成盐。 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
密码编码器。
根据migration guide,我必须迁移现有密码:
The format is intended to work with the DigestPasswordEncoder that was found in the Spring Security core module. However, the passwords will need to be migrated to include any salt with the password since this API provides Salt internally vs making it the responsibility of the user. To migrate passwords from the SaltSource use the following: String salt = saltSource.getSalt(user); String s = salt == null ? null : "{" + salt + "}"; String migratedPassword = s + user.getPassword();
问题: 密码迁移部分我不清楚的是结合了新的密码存储格式{id}encodedPassword
,其中使用了id
用于选择相应的密码编码器和盐部分。
根据 migration guide 我必须在存储的密码中添加 {sha256}
前缀,因此 DelegatingPasswordEncoder
将选择正确的解码器,但是如何处理 salt
部分呢?
我的理解如下:
首先,我必须定义 DelegatingPasswordEncoder
,如果我不在密码中添加 id
前缀,我必须使用 DelegatingPasswordEncoder.setDefaultPasswordEncoderForMatches
方法设置默认密码编码器以获取旧密码编码器.
接下来,在自定义AuthenticationProvider
服务class中实现认证逻辑,其中注入passwordEncoder
用于密码匹配校验。在调用 PasswordEncoder.matches(CharSequence rawPassword, String encodedPassword);
之前,我必须添加将格式化编码密码以匹配 {salt}password
格式的代码。
下一步是添加成功的身份验证侦听器,它将重新编码密码以匹配 {bcrypt}password
格式并将其存储到数据库中。因此,在下次用户登录尝试时,将改为调用 BCryptPasswordEncoder
密码编码器。
迁移所有密码后,我将能够删除自定义的 SaltSource-wise 内容和成功的身份验证侦听器。
如果我错了或者遗漏了什么,请纠正我。谢谢。
您只需要做两件事。
- 迁移密码以在模式中包含盐
{salt}<password-hash>
- 配置
DelegatingPasswordEncoder
并将正确配置的MessageDigestPasswordEncoder
设置为默认值。因此,如果未指定编码,它将回退到那个编码。
如果您想即时转换密码,您可以使用成功处理程序并更新记录以使用 BCrypt/SCrypt 而不是您现在拥有的内容。