1. Обзор
В Spring Security 4 можно было хранить пароли в виде простого текста с использованием аутентификации в памяти.
Серьезный пересмотр процесса управления паролями в версии 5 представил более безопасный механизм по умолчанию для кодирования и декодирования паролей. Это означает, что если ваше приложение Spring хранит пароли в виде простого текста, обновление до Spring Security 5 может вызвать проблемы.
В этом кратком руководстве мы опишем одну из этих потенциальных проблем и продемонстрируем решение.
2. Весенняя безопасность 4
Мы начнем с демонстрации стандартной конфигурации безопасности, обеспечивающей простую аутентификацию в памяти (действительно для Spring 4):
@Configuration
public class InMemoryAuthWebSecurityConfigurer
extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.inMemoryAuthentication()
.withUser("spring")
.password("secret")
.roles("USER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/private/**")
.authenticated()
.antMatchers("/public/**")
.permitAll()
.and()
.httpBasic();
}
}
Эта конфигурация определяет аутентификацию для всех /private/
отображенных методов и общий доступ для всего в /public/.
Если мы используем ту же конфигурацию в Spring Security 5, мы получим следующую ошибку:
java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
Ошибка сообщает нам, что данный пароль не может быть декодирован, так как кодировщик паролей не был настроен для нашей аутентификации в памяти .
3. Весенняя безопасность 5
Мы можем исправить эту ошибку, определив делегирующий
PasswordEncoder
с классом PasswordEncoderFactories .
Мы используем этот кодировщик для настройки нашего пользователя с помощью AuthenticationManagerBuilder:
@Configuration
public class InMemoryAuthWebSecurityConfigurer
extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
auth.inMemoryAuthentication()
.withUser("spring")
.password(encoder.encode("secret"))
.roles("USER");
}
}
Теперь, с этой конфигурацией, мы храним наш пароль в памяти с помощью BCrypt в следующем формате:
{bcrypt}$2a$10$MF7hYnWLeLT66gNccBgxaONZHbrSMjlUofkp50sSpBw2PJjUqU.zS
Хотя мы можем определить собственный набор кодировщиков паролей, рекомендуется придерживаться кодировщиков по умолчанию , предоставленных в PasswordEncoderFactories
.
3.2. Нооппассвордэнкодер
Если по какой-либо причине мы не хотим кодировать настроенный пароль, мы можем использовать NoOpPasswordEncoder
.
Для этого мы просто добавляем перед фразой-паролем, которую мы предоставляем методу password() , идентификатор
{noop}
:
@Configuration
public class InMemoryNoOpAuthWebSecurityConfigurer
extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.inMemoryAuthentication()
.withUser("spring")
.password("{noop}secret")
.roles("USER");
}
}
Таким образом, Spring Security будет использовать NoOpPasswordEncoder
под капотом, когда сравнивает пароль, предоставленный пользователем, с паролем, который мы настроили выше.
Обратите внимание, однако, что мы никогда не должны использовать этот подход в рабочем приложении! Как говорится в официальной документации, NoOpPasswordEncoder
объявлен устаревшим , чтобы указать, что это устаревшая реализация, и ее использование считается небезопасным .
3.3. Перенос существующих паролей
Мы можем обновить существующие пароли до рекомендованных стандартов Spring Security 5:
- Обновление сохраненных паролей в виде простого текста с закодированным значением:
String encoded = new BCryptPasswordEncoder().encode(plainTextPassword);
- Префикс хэшированных сохраненных паролей с их известным идентификатором кодировщика:
{bcrypt}$2a$10$MF7hYnWLeLT66gNccBgxaONZHbrSMjlUofkp50sSpBw2PJjUqU.zS
{sha256}97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0
- Запрос пользователей на обновление своих паролей, когда механизм кодирования сохраненных паролей неизвестен
4. Вывод
В этом кратком примере мы обновили действительную конфигурацию аутентификации в памяти Spring 4 до Spring 5, используя новый механизм хранения паролей.
Как всегда, вы можете найти исходный код в проекте GitHub .