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

Новое Хранилище Паролей В Spring Security 5

Краткое руководство по пониманию шифрования паролей в Spring Security 5 и переходу на более совершенные алгоритмы шифрования.

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

1. введение

С последним весенним выпуском системы безопасности многое изменилось. Одним из таких изменений является то, как мы можем обрабатывать кодировку паролей в наших приложениях.

В этом уроке мы рассмотрим некоторые из этих изменений.

Позже мы увидим, как настроить новый механизм делегирования и как обновить существующую кодировку пароля, чтобы наши пользователи не узнали ее.

2. Соответствующие изменения в весенней безопасности 5.x

Команда безопасности Spring объявила PasswordEncoder в org.springframework.security.authentication.encoding устаревшим. Это был логичный шаг, так как старый интерфейс не был предназначен для случайно сгенерированной соли. Следовательно, версия 5 удалила этот интерфейс.

Кроме того, Spring Security изменяет способ обработки закодированных паролей. В предыдущих версиях каждое приложение использовало только один алгоритм кодирования пароля.

По умолчанию StandardPasswordEncoder справился с этим. Он использовал SHA-256 для кодирования. Изменив кодер пароля, мы могли бы переключиться на другой алгоритм. Но наше приложение должно было придерживаться только одного алгоритма.

Версия 5.0 вводит концепцию делегирования кодирования паролей. Теперь мы можем использовать разные кодировки для разных паролей. Spring распознает алгоритм по идентификатору, предваряющему закодированный пароль.

Вот пример пароля, закодированного в bcrypt:

{bcrypt}$2b$12$FaLabMRystU4MLAasNOKb.HUElBAabuQdX59RWHq5X.9Ghm692NEi

Обратите внимание, как bcrypt указан в фигурных скобках в самом начале.

3. Конфигурация делегирования

Если хэш пароля не имеет префикса, процесс делегирования использует кодер по умолчанию. Следовательно, по умолчанию мы получаем StandardPasswordEncoder.

Это делает его совместимым с конфигурацией по умолчанию предыдущих версий Spring Security.

В версии 5 Spring Security вводит PasswordEncoder Factories.create Делегирующий кодер паролей(). Этот заводской метод возвращает сконфигурированный экземпляр делегирования PasswordEncoder .

Для паролей без префикса этот экземпляр обеспечивает только что упомянутое поведение по умолчанию. И для хэшей паролей, содержащих префикс, делегирование выполняется соответствующим образом.

Команда Spring Security перечисляет поддерживаемые алгоритмы в последней версии соответствующего JavaDoc .

Конечно, Spring позволяет нам настроить это поведение.

Предположим, мы хотим поддержать:

  • bcrypt как наш новый дефолт
  • скрипт в качестве альтернативы
  • SHA-256 в качестве используемого в настоящее время алгоритма.

Конфигурация для этой настройки будет выглядеть следующим образом:

@Bean
public PasswordEncoder delegatingPasswordEncoder() {
    PasswordEncoder defaultEncoder = new StandardPasswordEncoder();
    Map encoders = new HashMap<>();
    encoders.put("bcrypt", new BCryptPasswordEncoder());
    encoders.put("scrypt", new SCryptPasswordEncoder());

    DelegatingPasswordEncoder passworEncoder = new DelegatingPasswordEncoder(
      "bcrypt", encoders);
    passworEncoder.setDefaultPasswordEncoderForMatches(defaultEncoder);

    return passworEncoder;
}

4. Перенос Алгоритма кодирования паролей

В предыдущем разделе мы рассмотрели, как настроить кодировку пароля в соответствии с нашими потребностями. Поэтому сейчас мы будем работать над тем, как переключить уже закодированный пароль на новый алгоритм.

Давайте представим , что мы хотим изменить кодировку с SHA256 на scrypt , однако мы не хотим, чтобы наш пользователь менял свои пароли.

Одним из возможных решений является использование запроса на вход в систему. На этом этапе мы можем получить доступ к учетным данным в виде обычного текста. Именно в этот момент мы можем взять текущий пароль и перекодировать его.

Следовательно, мы можем использовать пружинные AuthenticationSuccessEvent за это. Это событие срабатывает после того, как пользователь успешно вошел в наше приложение.

Вот пример кода:

@Bean
public ApplicationListener
  authenticationSuccessListener( PasswordEncoder encoder) {
    return (AuthenticationSuccessEvent event) -> {
        Authentication auth = event.getAuthentication();

        if (auth instanceof UsernamePasswordAuthenticationToken
          && auth.getCredentials() != null) {

            CharSequence clearTextPass = (CharSequence) auth.getCredentials();
            String newPasswordHash = encoder.encode(clearTextPass);

            // [...] Update user's password

            ((UsernamePasswordAuthenticationToken) auth).eraseCredentials();
        }
    };
}

В предыдущем фрагменте:

  • Мы получили пароль пользователя в виде открытого текста из предоставленных данных аутентификации
  • Создал новый хэш пароля с новым алгоритмом
  • Удалил пароль открытого текста из маркера аутентификации

По умолчанию извлечение пароля в виде открытого текста невозможно, поскольку Spring Security удаляет его как можно скорее.

Следовательно, нам нужно настроить Spring так, чтобы он сохранял текстовую версию пароля.

Кроме того, нам необходимо зарегистрировать делегирование кодирования:

@Configuration
public class PasswordStorageWebSecurityConfigurer
  extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) 
      throws Exception {
        auth.eraseCredentials(false)
          .passwordEncoder(delegatingPasswordEncoder());
    }

    // ...
}

5. Заключение

В этой краткой статье мы рассказали о некоторых новых функциях кодирования паролей, доступных в 5.x.

Мы также видели, как настроить несколько алгоритмов кодирования паролей для кодирования наших паролей. Кроме того, мы исследовали способ изменить кодировку пароля, не нарушая существующую.

Наконец, мы описали, как использовать весенние события для прозрачного обновления зашифрованного пароля пользователя, что позволяет нам легко изменять нашу стратегию кодирования, не раскрывая этого нашим пользователям.

Наконец, как всегда, все примеры кода доступны в нашем репозитории GitHub .