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.