将 Shiro 散列密码迁移到 Spring 安全散列密码

Migrating Shiro hashed passwords to Spring Security hashed passwords

Spring 启动 2.6.2 网络应用程序...

考虑将所有 shiro 散列密码迁移到 spring 安全散列密码(使用 Pbkdf2PasswordEncoder)

到目前为止,我正在研究的是将 shiro 哈希重构为正确的格式,以便 spring 密码编码器成功匹配。

获取样本 shiro 哈希:

$shiro1$SHA-512000$wnjBM5pWpwN5784Aq7i7QA==$IqJ6XdwuKtCNqJCu982CzR6b4A3lnGp2F/WD8tmwVC7SAnOgeuUgtBbJ/ki9FqiIbX/ngF9RJd+5iy971d88cg==

在我的自定义用户详细信息服务 loadUserByUsername 方法中,我将密码哈希字符串拆分为 $ 字符,并重新 assemble 它以便在首次登录时,Spring 可以正确匹配哈希。

不清楚的是 Spring 在密码哈希中使用的格式来表示不同的部分...

注意:我的 shiro 实现使用了私有盐以及随机盐,50000 次迭代 SHA-512..

来自自定义用户详细信息服务的代码示例:

String[] pwdParts = user.getPassword().split("\$");
String privateSalt = "myprivatesalt";

    UserDetails coreUser = User.withUsername(username)
            .password(privateSalt + pwdParts[3] + pwdParts[4])
            .roles(roles.toArray(new String[0])).authorities(permissions.toArray(new String[0]))
            .accountLocked(user.isLocked()).build();

    CurrentUser currentUser = new CurrentUser(username, coreUser.getPassword(), coreUser.getAuthorities());

我走的路对吗?当前,Spring 在编码中登录失败:

@Bean
public PasswordEncoder encoder() {
    Pbkdf2PasswordEncoder pe = new Pbkdf2PasswordEncoder(myPrivateSalt, 50000, 512);
    pe.setAlgorithm(SecretKeyFactoryAlgorithm.PBKDF2WithHmacSHA512);
    return pe;
}

我的目标是避免让用户重置密码,并希望在他们首次登录我们的新版本应用程序时在后台静默更新密码。

原因是Spring安全性不包括哈希值中的算法和轮数。

您可以像这样实现自己的编码器来保持相同的哈希值:

public class ShiroSpringPbkdf2PasswordEncoder implements PasswordEncoder {

    private static final SHIRO_PREFIX = "$shiro1$SHA-512000$";

    private final Pbkdf2PasswordEncoder encoder =
        new Pbkdf2PasswordEncoder(myPrivateSalt, 50000, 512);

    public String encode(CharSequence rawPassword) {
        return SHIRO_PREFIX + this.encoder.encode(rawPassword);
    }

    public boolean matches(CharSequence rawPassword, String encodedPassword)     {
        if (encodedPassword.startsWith(SHIRO_PREFIX)) {
            return this.encoder.matches(rawPassword, encodedPassword.substring(SHIRO_PREFIX.length()));
        }
        return this.encoder.matches(rawPassword, encodedPassword);
    }
}

(因为你还有一个额外的盐,所以除了上面的操作之外,还有一些额外的字符串操作要做。)

关于迁移密码,您可以发布工具 PasswordEncoder#upgradeEncoding 查看编码值并决定是否需要更改并发布执行实际升级的 UserDetailsPasswordService

由于 Spring 安全性目前尚未在其 PBKDF2 哈希中包含算法和轮次,因此您保留哈希的原样可能会有一些价值。 Once Spring Security does support that,是时候迁移格式了。