«1. Обзор

В этой статье обсуждается важная часть процесса регистрации — кодирование пароля — в основном без сохранения пароля в открытом виде.

Существует несколько механизмов кодирования, поддерживаемых Spring Security, и в этой статье мы будем использовать BCrypt, так как обычно это лучшее доступное решение.

Большинство других механизмов, таких как MD5PasswordEncoder и ShaPasswordEncoder, используют более слабые алгоритмы и в настоящее время устарели.

2. Определение кодировщика паролей

Мы начнем с определения простого BCryptPasswordEncoder как bean-компонента в нашей конфигурации:

@Bean
public PasswordEncoder encoder() {
    return new BCryptPasswordEncoder();
}

Старые реализации, такие как SHAPasswordEncoder, требовали от клиента передать значение соли при кодировании пароля.

Однако вместо этого BCrypt будет внутренне генерировать случайную соль. Это важно понимать, потому что это означает, что каждый вызов будет иметь разный результат, поэтому нам нужно кодировать пароль только один раз.

Чтобы эта случайная генерация соли работала, BCrypt будет хранить соль внутри самого хеш-значения. Например, в следующем хеш-значении:

$2a$10$ZLhnHxdpHETcxmtEStgpI./Ri1mksgJ9iDP36FmfMdYyVg9g0b2dq

Есть три поля, разделенные символом $:

  1. The “2a” represents the BCrypt algorithm version
  2. The “10” represents the strength of the algorithm
  3. The “ZLhnHxdpHETcxmtEStgpI.” part is actually the randomly generated salt. Basically, the first 22 characters are salt. The remaining part of the last field is the actual hashed version of the plain text

Кроме того, имейте в виду, что алгоритм BCrypt генерирует строку длиной 60, поэтому нам нужно убедиться, что пароль будет храниться в столбце, который может вместить его. Распространенной ошибкой является создание столбца другой длины, а затем получение ошибки «Неверное имя пользователя или пароль» во время аутентификации.

3. Закодируйте пароль при регистрации

Теперь мы будем использовать PasswordEncoder в нашей UserService для хеширования пароля в процессе регистрации пользователя:

Пример 3.1. – UserService хэширует пароль

@Autowired
private PasswordEncoder passwordEncoder;

@Override
public User registerNewUserAccount(UserDto accountDto) throws EmailExistsException {
    if (emailExist(accountDto.getEmail())) {
        throw new EmailExistsException(
          "There is an account with that email adress:" + accountDto.getEmail());
    }
    User user = new User();
    user.setFirstName(accountDto.getFirstName());
    user.setLastName(accountDto.getLastName());
    
    user.setPassword(passwordEncoder.encode(accountDto.getPassword()));
    
    user.setEmail(accountDto.getEmail());
    user.setRole(new Role(Integer.valueOf(1), user));
    return repository.save(user);
}

4. Кодирование пароля при аутентификации

Давайте теперь займемся второй половиной этого процесса и кодируем пароль при аутентификации пользователя.

Во-первых, нам нужно внедрить bean-компонент кодировщика паролей, который мы определили ранее, в нашего поставщика аутентификации:

@Autowired
private UserDetailsService userDetailsService;

@Bean
public DaoAuthenticationProvider authProvider() {
    DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
    authProvider.setUserDetailsService(userDetailsService);
    authProvider.setPasswordEncoder(encoder());
    return authProvider;
}

Конфигурация безопасности проста:

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

И, наконец, нам нужно сослаться на этого провайдера аутентификации в нашей XML-конфигурации безопасности:

<authentication-manager>
    <authentication-provider ref="authProvider" />
</authentication-manager>

Или, если вы используете конфигурацию Java:

@Configuration
@ComponentScan(basePackages = { "com.baeldung.security" })
@EnableWebSecurity
public class SecSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authProvider());
    }
    
    ...
}

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

Этот краткий учебник продолжает серию «Регистрация», показывая, как правильно хранить пароль в базе данных, используя простую, но очень мощную реализацию BCrypt.

Полную реализацию этого руководства по регистрации с помощью Spring Security можно найти на GitHub.

Next »

The Registration API becomes RESTful

« Previous

Spring Security Registration – Resend Verification Email