У меня есть приложение REST api, в котором учетные данные хранятся в виде хэшей в таблице базы данных. Кроме того, у меня есть другое приложение, которое управляет учетными данными для первого приложения. Я создал в обоих приложениях DelagtingPasswordEncoder.
@Bean
public PasswordEncoder delegatingPasswordEncoder() {
PasswordEncoder defaultEncoder = NoOpPasswordEncoder.getInstance();
Map<String, PasswordEncoder> encoders = new HashMap<>();
encoders.put("bcrypt", new BCryptPasswordEncoder());
encoders.put("scrypt", new SCryptPasswordEncoder());
DelegatingPasswordEncoder passworEncoder = new DelegatingPasswordEncoder("bcrypt", encoders);
passworEncoder.setDefaultPasswordEncoderForMatches(defaultEncoder);
return passworEncoder;
}
Когда я пытаюсь выполнить аутентификацию на REST api с учетными данными, сгенерированными административным приложением, я получаю Unauthorized 401. Хэш bcrypt, сгенерированный в приложении администратора, не может быть сопоставлен bcrypt приложения REST api. Я предполагаю, что случайная соль, сгенерированная bcrypt, также зависит от контекста, в котором она инициализирована?
Мы использовали базовую аутентификацию для теста с правильным паролем, сгенерированным приложением администрирования перед сохранением его в виде хэша в базе данных.
Оба приложения используют одну и ту же базу данных, но в остальном независимы друг от друга.
Можно ли использовать bcrypt в обоих приложениях или как лучше всего обмениваться паролями между обоими приложениями?
Вам не нужно совместно использовать кодировщик BCrypt между приложениями.
Структура хэша BCryptPasswordEncoder
представляет собой конкатенацию:
Когда вы выполняете аутентификацию, вы в основном получаете имя пользователя и пароль из запроса пользователя, извлекаете пользователя на основе предоставленного имени пользователя из базы данных, извлекаете алгоритм хеширования, количество итераций и соль из хешированного пароля из базы данных, хеш пароль запроса на основе этих данных, а затем сравнить хэши. При аутентификации пользователя не происходит генерации соли. Соль генерируется только при создании или обновлении пароля.
Обратите внимание, что алгоритм хеширования, количество итераций и извлечение соли выполняются негласно методом matches
из BCryptPasswordEncoder
(который принимает в качестве аргументов хешированный пароль и простой пароль).
Я предполагаю, что вы не используете метод matches
из BCryptPasswordEncoder
для сравнения пароля запроса с паролем БД, а повторно хешируете пароль запроса и сравниваете полученный хэш с хешем базы данных. Это не сработает, поскольку закодированный метод сгенерирует новую соль, с помощью которой будет хешировать пароль, что приведет к другим хешам.
У меня есть способ хеширования паролей в открытом виде при первой аутентификации. У меня есть это для миграции. Мы помещаем пароли в виде открытого текста в базу данных, и при первом запросе аутентификации они хешируются, и хешированное значение сохраняется. Затем проверяется только хешированное значение с помощью метода совпадений. Это отлично работает в приложении REST. Только для хэшей, сгенерированных приложением администрирования, не работает. В обоих приложениях я генерирую компонент DelegatingPasswordEncoder, который автоматически подключается к службам для генерации хэша посредством кодирования.
Так не важно, что в разных приложениях есть разные бины? В любом случае хеш bcrypt должен быть проверен с помощью метода совпадений?
Да, BCrypt - это детерминированный алгоритм. При одном и том же вводе он всегда будет генерировать один и тот же вывод.
Моя реализация была неправильной. Теперь я просто создаю независимый BcryptPasswordEncoder и сохраняю пароль в приложении ADMIN, и приложение API может сопоставить его. Так что все работает как положено