Рубрики
Без рубрики

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

Узнайте, как избежать исключения IllegalArgumentException при переносе текстовых паролей в Spring Security 5

Автор оригинала: baeldung.

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();
    }
}

Эта конфигурация определяет аутентификацию для всех /частных/ сопоставленных методов и открытый доступ для всего, что находится в разделе /public/.

Если мы используем ту же конфигурацию в Spring Security 5, мы получим следующую ошибку:

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

Ошибка говорит нам о том, что данный пароль не может быть декодирован, так как кодировщик паролей не был настроен для нашей аутентификации в памяти .

3. Пружинная безопасность 5

Мы можем исправить эту ошибку, определив Делегирование PasswordEncoder с помощью класса PasswordEncoder Factories .

Мы используем этот кодер для настройки нашего пользователя с помощью 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

Если по какой-либо причине мы не хотим кодировать настроенный пароль, мы можем использовать 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 .