Перейти к основному содержимому

Кодировщик паролей по умолчанию в Spring Security 5

· 3 мин. чтения

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 .