Codificador de senha padrão no Spring Security 5

Codificador de senha padrão no Spring Security 5

1. Visão geral

No Spring Security 4, era possível armazenar senhas em texto sem formatação usando a autenticação na memória.

Uma grande revisão do processo de gerenciamento de senhas na versão 5 introduziu um mecanismo padrão mais seguro para codificar e decodificar senhas. Isso significa que, se o aplicativo Spring armazenar senhas em texto sem formatação, a atualização para o Spring Security 5 poderá causar problemas.

Neste breve tutorial, descreveremos um desses problemas potenciais e demonstraremos uma solução para o problema.

2. Spring Security 4

Começaremos mostrando uma configuração de segurança padrão que fornece autenticação simples na memória (válida para Spring 4):

@Configuration
public class InMemoryAuthWebSecurityConfigurer
  extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth)
      throws Exception {
        auth.inMemoryAuthentication()
          .withUser("spring")
          .password("secret")
          .roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
          .antMatchers("/private/**")
          .authenticated()
          .antMatchers("/public/**")
          .permitAll()
          .and()
          .httpBasic();
    }
}

Esta configuração define autenticação para todos os métodos mapeados de/private/ e acesso público para tudo em/public/.

Se usarmos a mesma configuração no Spring Security 5, obteremos o seguinte erro:

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

O erro nos diz que a senha fornecidacouldn’t be decoded since no password encoder was configured for our in-memory authentication.

3. Spring Security 5

Podemos consertar este erro definindo umDelegatingPasswordEncoder com a classePasswordEncoderFactories.

Usamos este codificador para configurar nosso usuário com oAuthenticationManagerBuilder:

@Configuration
public class InMemoryAuthWebSecurityConfigurer
  extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth)
      throws Exception {
        PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        auth.inMemoryAuthentication()
          .withUser("spring")
          .password(encoder.encode("secret"))
          .roles("USER");
    }
}

Agora, com esta configuração, estamos armazenando nossa senha na memória usando BCrypt no seguinte formato:

{bcrypt}$2a$10$MF7hYnWLeLT66gNccBgxaONZHbrSMjlUofkp50sSpBw2PJjUqU.zS

Embora possamos definir nosso próprio conjunto de codificadores de senha, é recomendado manter odefault encoders fornecido emPasswordEncoderFactories.

3.1. Migrando senhas existentes

Podemos atualizar as senhas existentes para os padrões recomendados do Spring Security 5:

  • Atualizando senhas armazenadas em texto sem formatação com seu valor codificado:

String encoded = new BCryptPasswordEncoder().encode(plainTextPassword);
  • Prefixar senhas armazenadas com hash com seu identificador de codificador conhecido:

{bcrypt}$2a$10$MF7hYnWLeLT66gNccBgxaONZHbrSMjlUofkp50sSpBw2PJjUqU.zS
{sha256}97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0
  • Solicitando que os usuários atualizem suas senhas quando o mecanismo de codificação das senhas armazenadas é desconhecido

4. Conclusão

Neste exemplo rápido, atualizamos uma configuração de autenticação válida na memória do Spring 4 para o Spring 5 usando o novo mecanismo de armazenamento de senha.

Como sempre, você pode encontrar o código-fonte emGitHub project.