如何在 Spring 引导安全中使用 HMAC-SHA512 对密码进行编码
How to encode password with HMAC-SHA512 in Spring Boot Security
我在 PHP 中有一个旧应用程序 运行,它使用函数 base64_encode(hash_hmac(“sha512”, $p_password, $p_salt, true))
对我们数据库中的密码进行编码。
我正在将此应用程序迁移到 Java Spring 引导,并希望在身份验证期间以完全相同的方式对密码进行编码。
我在这个 post and I also learnt that we can have several password encoders for old and new users with https://spring.io/blog/2017/11/01/spring-security-5-0-0-rc1-released#constructing-delegatingpasswordencoder
中找到了如何使用 Java 制作相同的散列方法
但我仍然找不到如何在 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;
}
我需要帮助来设置正确的密码编码器以在我的身份验证过程中使用 HMAC-SHA512 Java Spring 并在第二次, 将它与 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 安全人员说:“使用 '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));
}
}
我在 PHP 中有一个旧应用程序 运行,它使用函数 base64_encode(hash_hmac(“sha512”, $p_password, $p_salt, true))
对我们数据库中的密码进行编码。
我正在将此应用程序迁移到 Java Spring 引导,并希望在身份验证期间以完全相同的方式对密码进行编码。
我在这个 post
但我仍然找不到如何在 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;
}
我需要帮助来设置正确的密码编码器以在我的身份验证过程中使用 HMAC-SHA512 Java Spring 并在第二次, 将它与 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 安全人员说:“使用 '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));
}
}