微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在 Spring Boot Security 中使用 HMAC-SHA512 编码密码

如何解决如何在 Spring Boot Security 中使用 HMAC-SHA512 编码密码

我有一个PHP 中运行的旧应用程序,它使用函数 base64_encode(hash_hmac(“sha512”,$p_password,$p_salt,true)) 在我们的数据库中对密码进行编码。 我正在将此应用程序迁移到 Java Spring Boot,并希望在身份验证期间以完全相同的方式对密码进行编码。

在这文章 Compute HMAC-SHA512 with secret key in java 中找到了如何使用 Java 制作相同的散列方法,并且我还了解到我们可以使用 https://spring.io/blog/2017/11/01/spring-security-5-0-0-rc1-released#constructing-delegatingpasswordencoder 为新老用户设置多个密​​码编码器

但我仍然找不到如何在 Spring 身份验证过程中集成此 hasing 方法的示例。我必须创建一个 PasswordEncoder bean,但我不知道在里面放什么。 我尝试了 Pbkdf2PasswordEncoder,因为它可以在我的应用程序中生成一些 SHA-512 哈希值,但我收到错误 Detected a Non-hex character at 1 or 2 position。 这可能是因为数据库中的密码没有以 {pbkdf2} 为前缀。以下代码是我目前用作 PasswordEncoder 的代码

@Bean
public PasswordEncoder passwordEncoder() {
     Pbkdf2PasswordEncoder passwordEncoder = new Pbkdf2PasswordEncoder("salt");
     passwordEncoder.setAlgorithm(Pbkdf2PasswordEncoder.SecretKeyFactoryAlgorithm.PBKDF2WithHmacSHA512);
     return passwordEncoder;
}

我需要帮助来设置正确的密码编码器以在我使用 Java Spring 的身份验证过程中使用 HMAC-SHA512,并在第二次将它与 BCrytPasswordEncoder 结合(对于新用户) 与 DelegatingPasswordEncoder。 也许它需要更新数据库中的密码以使用正确的编码器作为前缀?

如果我的问题不够准确或缺少信息,请向我询问更多详细信息:)

解决方法

您需要将 DelegatingPasswordEncoder 添加到您的项目配置文件中。 DelegatingPasswordEncoder 充当 PasswordEncoder,当我们必须从一组实现中进行选择时,我们会使用它。:

@Configuration
public class ProjectConfig extends WebSecurityConfigurerAdapter {       
    
  @Bean
  public PasswordEncoder passwordEncoder() {
      Map<String,PasswordEncoder> encoders = new HashMap<>();  
    
    Pbkdf2PasswordEncoder bcryprPe = new Pbkdf2PasswordEncoder("salt");       
    bcryprPe.setAlgorithm(
       Pbkdf2PasswordEncoder.SecretKeyFactoryAlgorithm.PBKDF2WithHmacSHA512);
    encoders.put("pbkdf2",pbkdf2Pe);
    // add other PasswordEncoder here: 
    encoders.put("scrypt",new SCryptPasswordEncoder());
      return new DelegatingPasswordEncoder("pbkdf2",encoders);
  }
}

return new DelegatingPasswordEncoder("pbkdf2",encoders); 

我们对 Spring Security 说:“使用‘pbkdf2’作为默认密码编码器”。

如果提供的哈希值为 {scrypt}12345,则 DelegatingPasswordEncoder 委托给 SCryptPasswordEncoder,如果没有前缀,应用程序将使用默认值。

,

我终于得到了我想要的。我创建了一个受 https://github.com/lathspell/java_test/blob/master/java_test_openldap/src/main/java/LdapSha512PasswordEncoder.java

启发的 PasswordEncoder 实现

WebSecurityConfig.java

@Bean
public PasswordEncoder passwordEncoder() {
        Map<String,PasswordEncoder> encoders = new HashMap<>();
        encoders.put("SSHA-512",new Hmac512PasswordEncoder("salt"));
        encoders.put("bcrypt",new BCryptPasswordEncoder());
        return new DelegatingPasswordEncoder("SSHA-512",encoders);
}

Hmac512PasswordEncoder.java

public class Hmac512PasswordEncoder implements PasswordEncoder {

private static final String SSHA512_PREFIX = "{SSHA-512}";
private static final String HMAC_SHA512 = "HmacSHA512";

private final String salt;

public Hmac512PasswordEncoder(String salt) {
    if (salt == null) {
        throw new IllegalArgumentException("salt cannot be null");
    }
    this.salt = salt;
}

public String encode(CharSequence rawPassword) {
    String result = null;

    try {
        Mac sha512Hmac = Mac.getInstance(HMAC_SHA512);
        final byte[] byteKey = Utf8.encode(salt);
        SecretKeySpec keySpec = new SecretKeySpec(byteKey,HMAC_SHA512);
        sha512Hmac.init(keySpec);
        byte[] macData = sha512Hmac.doFinal(Utf8.encode(rawPassword.toString()));

        result = SSHA512_PREFIX + Base64.getEncoder().encodeToString(macData);
        //result = bytesToHex(macData);
    } catch (InvalidKeyException | NoSuchAlgorithmException e) {
        e.printStackTrace();
    }

    return result;
}

public boolean matches(CharSequence rawPassword,String encodedPassword) {
    if (rawPassword == null || encodedPassword == null) {
        return false;
    }

    String encodedRawPass = encode(rawPassword);

    return MessageDigest.isEqual(Utf8.encode(encodedRawPass),Utf8.encode(encodedPassword));
}
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。