首页 文章

Spring安全性3.1.4和ShaPasswordEncoder弃用

提问于
浏览
14

今天我将我正在处理的应用程序的spring安全版本从3.1.3升级到3.1.4,我注意到了 org.springframework.security.authentication.encoding.ShaPasswordEncoder 类的弃用警告 .

所以我切换到了新的 org.springframework.security.crypto.password.StandardPasswordEncoder 实现 .

我有它工作,我能够注册一个新用户并登录我的应用程序,但是,我担心,我无法使用以前的ShaPasswordEncoder和我的自定义盐生成的密码登录 .

由于我已经注册了许多用户的数据库,我应该怎么做才能切换实现而不会使旧的编码密码失效?它甚至可能吗?

另见:How to use new PasswordEncoder from Spring Security

3 回答

  • 18

    如果您想切换到更安全的密码编码机制,那么我建议您使用BCrypt . 我会使用这样的东西来迁移你的用户:

    // Implement the old PasswordEncoder interface
    public class MigrateUsersPasswordEncoder implements PasswordEncoder {
        @Autowired
        ShaPasswordEncoder legacyEncoder;
        @Autowired
        JdbcTemplate template;
    
        BCryptPasswordEncoder bcryptEncoder = new BCryptPasswordEncoder();
    
        @Override
        public String encodePassword(String rawPass, Object salt) {
            return bcryptEncoder.encode(rawPass);
        }
    
        @Override
        public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
            if (legacyEncoder.isPasswordValid(encPass, rawPass, salt)) {
                template.update("update users set password = ? where password = ?", bcryptEncoder.encode(rawPass), encPass);
                return true;
            }
            return bcryptEncoder.matches(rawPass, encPass);
        }
    }
    

    您可以按密码字段的格式检查已迁移的用户比例 . BCrypt字符串具有以 $ 符号开头的独特语法 .

    其中一个答案指出此代码可能会意外地同时更新多个密码 . 问题是使用了定制盐,因此如果随机选择盐,碰撞的可能性可以忽略不计,但情况可能并非总是如此 . 如果更新了两个密码,问题是什么?然后可以从bcrypt哈希中检测到帐户具有相同的密码 . 无论如何都是这种情况,因为它要求SHA哈希值相同才能进行更新 . 如果您认为它可能是一个问题(例如,由于选择的盐很差或甚至使用未加盐的哈希值),那么修改SQL以检测它并使用单独的BCrypt哈希值执行多个更新将是微不足道的 .

  • 1

    我试图在接受的答案中添加评论,但是,我还没有足够的信誉 . :(

    我相信接受答案的代码片段在更新数据库中的密码时可能会有危险 . 如果ShaPasswordEncoder在加密时产生相同的结果(这就是假设可以找到旧密码的原因,并且我确认这至少在ShaPasswordEncoder上使用空盐时确实如此),你仍然无法保证密码在所有用户中都是唯一的 . 您可以偶然地与系统上的另一个用户共享相同的密码,并且该SQL代码最终会更改碰巧有您密码的所有用户 .

    我认为最安全的策略是不更新用户的密码,而是提供一个迁移策略,计划最终删除ShaPasswordEncoder .

    • 使用提供的示例代码 .

    • 删除更新数据库的代码 .

    • 添加一个功能,如"Forgot your password"或"Generate a new password",以处理用户在删除ShaPasswordEncoder时未创建新密码的最终情况 . 就像升级到Spring Security并将其删除一样,或者选择自己删除它 .

    • 更新您的文档或明确指出,在软件的下一个主要版本中,用户将不得不重新保存其密码,或者必须使用前面提到的密码重置功能 .

    • 为用户提供主要版本发布周期的宽限期以进行转换(他们可能不会这样做,只是被重置密码捕获) .

  • 3

    这是一个很好的问题,我期待着阅读一些答案 .

    AFAIK在单个批量更新中是不可能的:您无法从散列中检索原始字符串 . 您必须在登录尝试期间检查提交的密码是否与策略匹配,并在必要时将其转换为新策略,但这意味着您必须使用两种编码策略,直到所有用户都已登录,因此所有密码都已转换 . 加入新开发人员并不十分方便,也不一定直观 .

相关问题