Autenticação em Memória com Spring Security no Spring Boot

Ao configurar o Spring Security em um projeto Spring Boot, o comportamento padrão geralmente fornece apenas um usuário gerado automaticamente. Para gerenciar múltiplas credenciais e perfis de acesso de forma simples, sem a necessidade imediata de um banco de dados, podemos utilizar a autenticação baseada em memória.

Existem duas abordagens principais para implementar esse modelo, conforme detalhado a seguir.

1. Configuração via Adaptador de Segurança

Uma das formas de definir usuários é estendendo a classe WebSecurityConfigurerAdapter e sobrescrevendo o método de gerenciamento de autenticação. É fundamental definir um codificador de senhas (PasswordEncoder), pois o Spring Security exige que as senhas armazenadas sigam um padrão de hash para validação.

@Configuration
public class SecurityConfigurador extends WebSecurityConfigurerAdapter {

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

    @Override
    protected void configure(AuthenticationManagerBuilder gerenciadorAuth) throws Exception {
        // Define o codificador para os usuários em memória
        User.UserBuilder usuarios = User.builder().passwordEncoder(criptografiaSenha()::encode);

        gerenciadorAuth.inMemoryAuthentication()
            .withUser(usuarios.username("admin").password("admin123").roles("ADMIN"))
            .withUser(usuarios.username("operador").password("op456").roles("USER"));
    }
}

No exemplo acima, criamos dois usuários distintos com papéis (roles) diferentes. Sem o BCryptPasswordEncoder, o sistema falharia ao tentar comparar a senha digitada com a armazenada, resultando em erro de autenticação mesmo com os dados corretos.

2. Implementação via Bean UserDetailsService

Uma abordagem mais modular e moderna consiste em expor um Bean do tipo UserDetailsService. Essa estratégia é útil pois isola a fonte de dados dos usuários, facilitando uma futura migração para consultas em banco de dados SQL ou NoSQL.

@Configuration
public class GestaoUsuariosConfig {

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

    @Bean
    public UserDetailsService provedorUsuarios(PasswordEncoder encoder) {
        // Criando usuários detalhados
        UserDetails user1 = User.builder()
            .passwordEncoder(encoder::encode)
            .username("dev_senior")
            .password("java888")
            .roles("DEVELOPER")
            .build();

        UserDetails user2 = User.builder()
            .passwordEncoder(encoder::encode)
            .username("manager")
            .password("pass999")
            .roles("MANAGER")
            .build();

        return new InMemoryUserDetailsManager(user1, user2);
    }
}

Nesse modelo, utilizamos o InMemoryUserDetailsManager, que é uma implementação pronta do Spring para gerenciar o armazenamento volátil de credenciais.

3. Verificação de Autenticação

Para testar se a autenticação está funcionando corretamente e identificar qual usuário está logado, podemos criar um endpoint REST que recupera os detalhes do contexto de segurança da aplicação.

@RestController
public class StatusController {

    private String recuperarNomeLogado() {
        Object informacao = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

        if (informacao instanceof UserDetails) {
            return ((UserDetails) informacao).getUsername();
        }
        
        return informacao.toString();
    }

    @GetMapping("/info-acesso")
    public String verificarStatus() {
        String usuarioAtual = recuperarNomeLogado();
        return "Sessão ativa para o usuário: " + usuarioAtual;
    }
}

Ao acessar o endpoint /info-acesso, o sistema solicitará o login via formulário padrão ou Basic Auth. Após o sucesso, o nome do usuário definido em memória será retornado na resposta da requisição.

Tags: Spring Security Spring Boot java authentication BCrypt

Publicado em 8-15 14:38