Хэшированный пароль в Spring Security в стандартной реализации аутентификации не работает после перезапуска приложения

Дано:

  1. SpringBoot приложение.
  2. Используется для авторизации стандартная форма ввода логина и пароля.
  3. Пароль хешируется через BCryptPasswordEncoder
  4. Пока приложение запущено - можно поменять в БД пароль на результат вызова passwordEncoder.encode("PasswordHere") - и авторизовываться через форму входа.
  5. Вот так выглядит подключение хэширования пароля:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
class WebSecurityConfiguration : WebSecurityConfigurerAdapter() {

    @Bean
    fun passwordEncoder() = BCryptPasswordEncoder()

    @Bean
    fun authenticationProvider(): DaoAuthenticationProvider =
            DaoAuthenticationProvider().apply {
                setUserDetailsService(userDetailsService)
                setPasswordEncoder(passwordEncoder())
            }

    @Autowired
    fun configureGlobal(auth: AuthenticationManagerBuilder) {
        auth
                .authenticationProvider(authenticationProvider())
                .userDetailsService(userDetailsService)
                .passwordEncoder(passwordEncoder())
    }

    override fun configure(http: HttpSecurity) {
        http
                .cors()
        http
                .csrf()
                .disable()
        http
                .authorizeRequests()
                .anyRequest()
                .authenticated()
        http
                .formLogin()
                .and()
                .logout()
                .permitAll()
    }
}

Проблема:

После перезапуска приложения ввод правильного пароля в форму входа выдаёт ошибку. При этом, если получить хэш пароля через passwordEncoder.encode("PasswordHere") и вручную его в БД вставить - всё работает до следующего перезапуска приложения.

Вопрос:

Таки что не так и как это исправить?

UPD:

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


Ответы (2 шт):

Автор решения: VincentVega

Хеш от passwordEncoder.encode() возвращается каждый раз разный, так как разные соли. Возможно ты сверяешь хеши методом Object.equals(), а для проверки равенства хешей используется специальный метод passwordEncoder.matches(CharSequence rawPassword, String encodedPassword), где rawPassword это пароль введенный юзером, а encodedPassword пароль из базы данных.

→ Ссылка
Автор решения: ЮрийСПб

К сожалению причиной ошибки была моя невнимательность. У меня на поле для пароля была поставлена аннотация @Converter, в которой использовался класс-конвертер, который при каждом обновлении юзера в БД (полученного ранее из БД) заново кэшировал уже закэшированный пароль. Естественно, после этого проверка на совпадение в недрах спринговой авторизации выдавала ошибку несовпадения паролей.

→ Ссылка