У меня есть проект Spring, использующий безопасность Spring. Я использовал Spring Boot 1.5, а теперь перешел на Spring Boot 2.0.
Я заметил, что Md5PasswordEncoder был удален в последней версии Spring Security. Вместо этого Md4PasswordEncoder все еще присутствует, даже если устарел (https://docs.spring.io/spring-security/site/docs/5.0.3.RELEASE/api/).
Должен ли я использовать внешний кодировщик MD5 или класс перемещен в другое место?




Вместо этого вы должны использовать org.springframework.security.crypto.password.PasswordEncoder. Здесь - хорошая статья о переходе на новый интерфейс.
Я нашел эту статью более интуитивной baeldung.com/spring-security-5-password-storage
Spring удалите MD5, потому что он уже недостаточно безопасен. Вам следует использовать Bcrypt.
Мне нужно использовать MD5, потому что платежный шлюз требует хеширования некоторой части запроса с помощью MD5. Это не мой выбор ;-) Я использую Bcrypt для всего остального.
Тот факт, что Md5PasswordEncoder прекратил свое существование, не означает, что Spring Security 5 не может создавать хэши MD5. Для этого используется new MessageDigestPasswordEncoder("MD5").
Есть два варианта, оба работают с новым DelegatingPasswordEncoder, который ожидает, что префикс пароля определяет алгоритм хеширования, например {MD5}password_hash:
Либо устанавливает кодировщик пароля по умолчанию на MD5 (в верхнем регистре!), Поэтому, если пароли не имеют префикса, применяется кодировщик по умолчанию:
PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
passwordEncoder.setDefaultPasswordEncoderForMatches(new MessageDigestPasswordEncoder("MD5"));
Или же префикс существующих хэшей паролей в базе данных с {MD5}. Таким образом, DelegatingPasswordEncoder делегирует хешеру MD5. Что-то вроде:
update myusertable set pwd = '{MD5}' || pwd;
Можете ли вы указать, какой пакет включить для PasswordEncoderFactories?
это должен быть org.springframework.security.crypto.factory.PasswordEncoderFactories от spring-security-core
Если вы хотите использовать MD5, вы можете настроить:
@Bean
public PasswordEncoder passwordEncoder() {
return new PasswordEncoder() {
@Override
public String encode(CharSequence charSequence) {
return getMd5(charSequence.toString());
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return getMd5(charSequence.toString()).equals(s);
}
};
}
public static String getMd5(String input) {
try {
// Static getInstance method is called with hashing SHA
MessageDigest md = MessageDigest.getInstance("MD5");
// digest() method called
// to calculate message digest of an input
// and return array of byte
byte[] messageDigest = md.digest(input.getBytes());
// Convert byte array into signum representation
BigInteger no = new BigInteger(1, messageDigest);
// Convert message digest into hex value
String hashtext = no.toString(16);
while (hashtext.length() < 32) {
hashtext = "0" + hashtext;
}
return hashtext;
}
// For specifying wrong message digest algorithms
catch (NoSuchAlgorithmException e) {
System.out.println("Exception thrown"
+ " for incorrect algorithm: " + e);
return null;
}
}
Мое решение, как показано ниже:
protected static String mergePasswordAndSalt(String password, Object salt, boolean strict) {
if (password == null) {
password = "";
}
if ((strict) && (salt != null) && ((salt.toString().lastIndexOf("{") != -1) || (salt.toString().lastIndexOf("}") != -1))) {
throw new IllegalArgumentException("Cannot use { or } in salt.toString()");
}
if ((salt == null) || ("".equals(salt))) {
return password;
}
return password + "{" + salt.toString() + "}";
}
public static String EncodingPassword(String password, String salt) {
String merge = mergePasswordAndSalt(password,salt,false);
return DigestUtils.md5Hex(merge);
}
используйте указанную выше функцию, чтобы заменить приведенный ниже код:
new Md5PasswordEncoder().encodePassword(String rawPass, Object salt);
Из исходного кода Md5PasswordEncoder в spring-security-core-3.1.4.RELEASE.jar мы можем узнать, как он обрабатывает пароль и соль:
//org.springframework.security.authentication.encoding.BasePasswordEncoder.class
protected String mergePasswordAndSalt(String password, Object salt, boolean strict)
{
if (password == null) {
password = "";
}
if ((strict) && (salt != null) && (
(salt.toString().lastIndexOf("{") != -1) || (salt.toString().lastIndexOf("}") != -1))) {
throw new IllegalArgumentException("Cannot use { or } in salt.toString()");
}
if ((salt == null) || ("".equals(salt))) {
return password;
}
return password + "{" + salt.toString() + "}";
}
Вам вообще не следует использовать
MD5.