Как использовать новый PasswordEncoder из Spring Безопасность
Как и в случае с Spring Security 3.1.4.RELEASE, старый org.springframework.security.authentication.encoding.PasswordEncoder
устарел в пользу org.springframework.security.crypto.password.PasswordEncoder
. Поскольку мое приложение еще не было выпущено для публики, я решил перейти к новому, а не устаревшему API.
До сих пор у меня был ReflectionSaltSource
, который автоматически использовал дату регистрации пользователя как пароль пользователя для пароля.
String encodedPassword = passwordEncoder.encodePassword(rawPassword, saltSource.getSalt(user));
В процессе входа в систему Spring также использовал мой beans, чтобы проверить, может ли пользователь войти или не может войти. Я не могу этого добиться в новом кодовом коде, поскольку стандартная реализация SHA-1 - StandardPasswordEncoder
имеет возможность добавлять глобальную секретную соль во время создания кодировщика.
Есть ли какой-либо разумный способ настройки с помощью не устаревшего API?
Ответы
Ответ 1
Если вы на самом деле не зарегистрировали ни одного пользователя с существующим форматом, тогда лучше было бы переключиться на использование кодировщика паролей BCrypt.
Это намного меньше хлопот, так как вам не нужно беспокоиться о соли вообще - детали полностью инкапсулированы в кодере. Использование BCrypt сильнее, чем использование простого алгоритма хэширования, а также стандарт, совместимый с приложениями, использующими другие языки.
На самом деле нет причин выбирать какие-либо другие параметры для нового приложения.
Ответ 2
Вот реализация BCrypt, которая работает для меня.
в spring -security.xml
<authentication-manager >
<authentication-provider ref="authProvider"></authentication-provider>
</authentication-manager>
<beans:bean id="authProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<beans:property name="userDetailsService" ref="userDetailsServiceImpl" />
<beans:property name="passwordEncoder" ref="encoder" />
</beans:bean>
<!-- For hashing and salting user passwords -->
<beans:bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
В классе java
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String hashedPassword = passwordEncoder.encode(yourpassword);
Для более подробного примера spring безопасности Нажмите здесь
Надеюсь, это поможет.
Спасибо
Ответ 3
У меня была аналогичная проблема. Мне нужно было сохранить устаревшие зашифрованные пароли (Base64/SHA-1/Random salt Encoded), так как пользователи не захотят менять свои пароли или перерегистрировать. Однако я также хотел использовать кодировщик BCrypt.
Мое решение состояло в том, чтобы написать декодер, сделанный на заказ, который проверяет, какой метод шифрования был использован перед сопоставлением (в скопированных с помощью $
).
Чтобы обойти проблему солей, я передаю в декодер конкатенированную строку соли + зашифрованный пароль через мой измененный объект пользователя.
Декодер
@Component
public class LegacyEncoder implements PasswordEncoder {
private static final String BCRYP_TYPE = "$";
private static final PasswordEncoder BCRYPT = new BCryptPasswordEncoder();
@Override
public String encode(CharSequence rawPassword) {
return BCRYPT.encode(rawPassword);
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
if (encodedPassword.startsWith(BCRYP_TYPE)) {
return BCRYPT.matches(rawPassword, encodedPassword);
}
return sha1SaltMatch(rawPassword, encodedPassword);
}
@SneakyThrows
private boolean sha1SaltMatch(CharSequence rawPassword, String encodedPassword) {
String[] saltHash = encodedPassword.split(User.SPLIT_CHAR);
// Legacy code from old system
byte[] b64salt = Base64.getDecoder().decode(saltHash[0].getBytes());
byte[] validHash = Base64.getDecoder().decode(saltHash[1]);
byte[] checkHash = Utility.getHash(5, rawPassword.toString(), b64salt);
return Arrays.equals(checkHash, validHash);
}
}
Пользовательский объект
public class User implements UserDetails {
public static final String SPLIT_CHAR = ":";
@Id
@Column(name = "user_id", nullable = false)
private Integer userId;
@Column(nullable = false, length = 60)
private String password;
@Column(nullable = true, length = 32)
private String salt;
.
.
@PostLoad
private void init() {
username = emailAddress; //To comply with UserDetails
password = salt == null ? password : salt + SPLIT_CHAR + password;
}
Вы также можете добавить крючок для повторного кодирования пароля в новом формате BCrypt и заменить его. Таким образом, поэтапный отказ от старого метода.
Ответ 4
Только что обошел Интернет, чтобы узнать об этом и о вариантах в Spring, я бы ответил на второй вопрос Luke, используйте BCrypt (он упоминается в исходный код в Spring).
Лучший ресурс, который я нашел, чтобы объяснить, почему хеш/соль и почему использовать BCrypt, является хорошим выбором здесь: Соленый пароль Хеширование - Выполнение этого права.