Spring Security: Autenticação com um UserDetailsService suportado por banco de dados

Spring Security: Autenticação com um UserDetailsService suportado por banco de dados

1. Visão geral

Neste artigo, mostraremos como criar um banco de dados personalizadoUserDetailsService para autenticação com Spring Security.

2. UserDetailsService

A interfaceUserDetailsService é usada para recuperar dados relacionados ao usuário. Ele possui um método chamadoloadUserByUsername() que pode ser substituído para personalizar o processo de localização do usuário.

Ele é usado porDaoAuthenticationProvider para carregar detalhes sobre o usuário durante a autenticação.

3. O modeloUser

Para armazenar usuários, criaremos uma entidadeUser que é mapeada para uma tabela de banco de dados, com os seguintes atributos:

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(nullable = false, unique = true)
    private String username;

    private String password;

    // standard getters and setters
}

4. Recuperando um usuário

Com o objetivo de recuperar um usuário associado a um nome de usuário, criaremos uma classeDAO usandoSpring Data estendendo a interfaceJpaRepository:

public interface UserRepository extends JpaRepository {

    User findByUsername(String username);
}

5. OUserDetailsService

Para fornecer nosso próprio serviço ao usuário, precisaremos implementar a interfaceUserDetailsService.

Vamos criar uma classe chamadaMyUserDetailsService que substitui o métodoloadUserByUsername() da interface.

Neste método, recuperamos o objetoUser usandoDAO e, se existir, envolvemos-o em um objetoMyUserPrincipal, que implementaUserDetails e o retorna:

@Service
public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) {
        User user = userRepository.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException(username);
        }
        return new MyUserPrincipal(user);
    }
}

Vamos definir a classeMyUserPrincipal da seguinte forma:

public class MyUserPrincipal implements UserDetails {
    private User user;

    public MyUserPrincipal(User user) {
        this.user = user;
    }
    //...
}

6. Configuração da mola

Demonstraremos os dois tipos de configurações Spring: XML e baseadas em anotação, que são necessárias para usar nossa implementaçãoUserDetailsService personalizada.

6.1. Configuração de anotação

Tudo o que precisamos fazer para habilitar nossoUserDetailsService  personalizado é adicioná-lo ao contexto de nosso aplicativo como um bean.

Como configuramos nossa classe com a anotação@Service, o aplicativo irá detectá-lo automaticamente durante a varredura de componente e criará um bean fora desta classe. Portanto, não há mais nada que precisamos fazer aqui.

Como alternativa, podemos:

  • configure-o emauthenticationManager usando o métodoAuthenticationManagerBuilder#userDetailsService

  • defina-o como uma propriedade em um beanauthenticationProvider personalizado e, em seguida, injete isso usando a funçãoAuthenticationManagerBuilder# authenticationProvider

6.2. Configuração XML

Por outro lado, para a configuração XML, precisamos definir um bean com o tipoMyUserDetailsService e injetá-lo no beanauthentication-provider do Spring:




    
        
        
    



    

7. Outras opções de autenticação baseada em banco de dados

OAuthenticationManagerBuilder oferece um outro método para configurar a autenticação baseada em JDBC em nosso aplicativo.

Teremos que configurarAuthenticationManagerBuilder.jdbcAuthentication com uma instânciaDataSource. Se nosso banco de dados seguirSpring User Schema, então as configurações padrão serão adequadas para nós.

Vimos uma configuração básica usando essa abordagem ema previous post.

OJdbcUserDetailsManager entity resultante desta configuração implementa oUserDetailsService too.

Como resultado, podemos concluir que esta configuração é mais fácil de implementar, especialmente se estivermos usando Spring Boot, que configuraDataSource automaticamente para nós.

Se precisarmos, de qualquer maneira, de um nível mais alto de flexibilidade, personalizando exatamente como o aplicativo irá buscar os detalhes do usuário, então vamos optar pela abordagem que seguimos neste tutorial.

8. Conclusão

Para resumir, neste artigo, mostramos como criar umUserDetailsService baseado em Spring personalizado com base em dados persistentes.

A implementação pode ser encontrada emthe GitHub project - este é um projeto baseado em Maven, portanto, deve ser fácil de importar e executar como está.