PasswordEncoder

PasswordEncoder не шифрует пароль для последующей расшифровки. Он вычисляет медленный односторонний password hash и проверяет введённое значение.

String stored = encoder.encode(rawPassword);
boolean matches = encoder.matches(candidate, stored);

Требования

  • соль должна быть уникальной и генерироваться алгоритмом;
  • функция должна быть намеренно дорогой;
  • параметры стоимости пересматриваются по возможностям инфраструктуры;
  • пароль не логируется и не передаётся после проверки дальше необходимого;
  • сравнение выполняется через matches, а не путём повторного сравнения строк.

Spring поддерживает адаптивные алгоритмы, например bcrypt, PBKDF2, scrypt и Argon2. Конкретный выбор зависит от доступной реализации, памяти, CPU и политики организации.

DelegatingPasswordEncoder

Формат с префиксом хранит алгоритм:

{bcrypt}$2a$...

Это позволяет читать старые hashes и записывать новые более сильным алгоритмом. При успешном входе можно проверить upgradeEncoding и пересчитать hash.

Типичные ошибки

  • SHA-256 без медленной password-функции;
  • одна общая ручная соль;
  • детерминированное сравнение encode(raw).equals(stored);
  • слишком низкая или чрезмерная стоимость без нагрузочного теста;
  • хранение raw password в событии или журнале.

Вопросы для повторения

  1. Можно ли расшифровать password hash? Нет, проверяется совпадение через вычисление.
  2. Почему два hash одного пароля различаются? Из-за случайной соли.
  3. Зачем префикс {id}? Выбрать encoder для проверки и поддержать миграцию алгоритмов.
  4. Почему обычный SHA недостаточен? Он слишком быстрый для перебора.
  5. Как обновить старые hashes? Перехешировать после успешной аутентификации или через контролируемый сброс.

Связано: Безопасность приложения Spring Security.