spring - 将 Spring 安全性 4.x(ShaPasswordEncoder 和每个用户的唯一盐)迁移到 5.x(BCryptPasswordEncoder)

我正在将 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

您只需要做两件事。

  1. 迁移密码以在模式 {salt}<password-hash> 中包含盐
  2. 配置 DelegatingPasswordEncoder 并将正确配置的 MessageDigestPasswordEncoder 设置为默认值。因此,如果没有指定编码,它将回退到那个编码。

如果您想即时转换密码,您可以使用 succes 处理程序执行此操作并更新记录以使用 BCrypt/SCrypt 而不是您现在拥有的。

相似文章