如何在spring boot security中使用hmac-sha512编码密码

4dc9hkyq  于 2021-07-13  发布在  Java
关注(0)|答案(2)|浏览(1064)

我有一个用php运行的老应用程序,它使用了这个函数 base64_encode(hash_hmac(“sha512”, $p_password, $p_salt, true)) 对数据库中的密码进行编码。我正在将这个应用程序迁移到javaspringboot,并希望在身份验证期间以完全相同的方式对密码进行编码。
我在这篇文章中发现了如何用java来做同样的散列方法,hmac-sha512用java来做密钥,我还了解到我们可以为新老用户提供多个密码编码器https://spring.io/blog/2017/11/01/spring-security-5-0-0-rc1-released#constructing-委派密码编码器
但是我仍然找不到一个例子来说明如何在spring身份验证过程中集成这个hasing方法。我必须创造一个 PasswordEncoder 比恩和我不知道该放什么进去。我试过了 Pbkdf2PasswordEncoder 因为它可以使一些sha-512哈希像在我的应用程序,但我得到的错误 Detected a Non-hex character at 1 or 2 position . 这可能是因为在数据库中密码的前缀不是{pbkdf2}。下面的代码是我目前使用的密码编码器

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

我需要帮助设置正确的密码编码器,以便在使用JavaSpring的身份验证过程中使用hmac-sha512,并在第二次使用时将其与 BCrytPasswordEncoder (针对新用户)具有 DelegatingPasswordEncoder . 也许它需要更新数据库中的密码,以正确的编码器作为前缀?
如果我的问题不够准确或信息缺失,请向我询问更多细节:)

wqlqzqxt

wqlqzqxt1#

您需要将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);

我们对springsecurity说:“使用'pbkdf2'作为默认密码编码器”。
如果提供的哈希是{scrypt}12345,delegatingpasswordencoder将委托给scryptpasswordencoder,如果没有前缀,应用程序将使用默认前缀。

ykejflvf

ykejflvf2#

我终于得到了我想要的。我创建了一个passwordencoder的实现,灵感来自https://github.com/lathspell/java_test/blob/master/java_test_openldap/src/main/java/ldapsha512passwordencoder.java
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));
}
}

相关问题