Как добавить шифрование в SHA256 для Basic auth в Spring

Я храню пароли юзеров в базе в зашифрованном виде - SHA256. Использую Basic auth и чтобы сейчас пройти авторизацию, я должен передавать пароль на контроллер тоже в SHA256. Можно ли как то переопределить SecurityConfig, чтобы пользователь мог передать пароль в исходном виде, но под капотом произошло шифрование этого пароля, и Spring сравнил этот зашифрованный пароль с зашифрованным паролем из базы?

Текущая реализация SecurityConfig:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    private final UserService userService;

    public SecurityConfig(UserService userService) {
        this.userService = userService;
    }

    @Bean
    @Override
    public UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        userService.getUsers().forEach(user -> manager.createUser(createUserDetails(user.getUserName(), user.getPassword())));
        return manager;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
                .anyRequest().authenticated()
                .and().httpBasic();
    }

    private UserDetails createUserDetails(String username, String password) {
        return User.withUsername(username)
                .password(encodePassword(password))
                .roles("USER")
                .build();
    }

    private String encodePassword(String vaultPassword) {
        PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        return encoder.encode(vaultPassword);
    }
}

UPD: новая версия конфигурации:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    private final UserService userService;

    public SecurityConfig(UserService userService) {
        this.userService = userService;
    }

    @Bean
    @Override
    public UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        userService.getUsers().forEach(user -> manager.createUser(createUserDetails(user.getUserName(), user.getPassword())));
        return manager;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
                .anyRequest().authenticated()
                .and().httpBasic();
    }

    private UserDetails createUserDetails(String username, String password) {
        return User.withUsername(username)
                .password(passwordEncoder().encode(password))
                .roles("USER")
                .build();
    }

    @Bean
    public DaoAuthenticationProvider daoAuthenticationProvider(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userDetailsService);
        authProvider.setPasswordEncoder(passwordEncoder);
        return authProvider;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }
}

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

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

Да, можно.

За такое поведение отвечает PasswordEncoder. Логика работы примерно такая:

  1. Пароль приходит в открытом виде;
  2. Spring Security определяет AuthenticationProvider, который ответственнен за аутентификацию пользователя для данного метода API. В Вашем случае это DaoAuthenticationProvider;
  3. DaoAuthenticationProvider шифрует пароль с помощью PasswordEncoder и делегирует поиск пользователя экземпляру UserDetailsService;
  4. UserDetailsService ищет пользователя по имени и зашифрованному паролю в БД;

Все, что нужно для этого сделать - объявить бин PasswordEncoder, например, так:

    @Bean
    private PasswordEncoder passwordEncoder() {
      return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }
→ Ссылка