#DIOProGrátis - Spring Security - Entenda o que nunca te contaram sobre o fluxo desse framework de autenticação de autorização
- #Spring Boot / Spring Framework
- #Spring Security / Spring Framework
- #REST
Autenticação
O fluxo de autenticação por meio do Spring Security é o seguinte:
Tendo em vista essa cadeia de dependências, a cofiguração do processo de autenticação por meio do Spring Security deverá obedecer a seguinte sequência:
- Definir uma classe que implemente a interface UserDetails
- Definir uma classe que implemente a interface UserDetailsService
- Definir a lógica de criptografia de senha ou utilizar uma implementação da interface PasswordEncoder fornecida pelo Spring Security
- Definir a lógica de autenticação a ser implementada ou utilizar uma implementação da interface AuthenticationProvider disponibilizada pelo Spring Security
- Implementar a interface AuthenticationManager ou utilizar uma implementação dessa interface construída por meio da classe AuthenticationManagerBuilder.
Após a configuração do Spring Security, será possível adicionar o AuthenticationManager como um bean ao contexto da aplicação por meio do método authenticationManagerBean() da classe WebSecurityConfigurerAdapter
O processo de autenticação tem dois objetivos no Spring Security:
- Prover ao AuthenticationManager as credenciais fornecidas pelo usuário para se autenticar
- Representar o usuário autenticado por meio da interface Authentication, que pode ser obtida a partir do SecurityContext: SecurityContextHolder.getContext().getAuthentication()
A interface Authentication dispõe de métodos para obter:
- authorities, que são permissões em alto nível atribuídas ao usuário, como papéis ou escopos. Permissões são definidas por Strings e, por padrão, prefixadas com 'ROLE_'
- credentials, geralmente uma senha, mas também pode ser um token.
- principal, que identifica o usuário. É geralmente uma implementação da interface UserDetails quando se autentica com usuário e senha
Authentication Filter
A primeira etapa deste processo ocorre no Spring Security Authentication Filter, que tem três responsabilidades:
- Extrair o usuário e a senha que foram fornecidos para autenticação
- Criar um token de autenticação usando UsernamePasswordAuthenticationToken, que é uma implementação da interface Authentication
- Delegar a continuação do processo de autenticação à interface AuthenticationManager, reponsável por analisar o token de autenticação e decidir se é uma credencial válida.
AuthenticationManager
A principal interface da estratégia de autenticação do Spring Security é AuthenticationManager, cujo único método (authenticate( )) pode fazer uma das seguintes coisas:
- Retornar uma Authentication se puder ser verificado que as credenciais apresentadas são válidas.
- Jogar uma exceção AuthenticationException se as credenciais apresentadas não forem válidas.
- Retornar null, se ela não conseguir decidir.
A implementação mais comum do AuthenticationManager é o ProviderManager, que possui uma lista de AuthenticationProviders aos quais é dada a oportunidade de indicar se a autenticação deveria ter sucesso, falhar ou indicar que não consegue decidir e deixar essa tarefa para o próximo AuthenticationProvider da lista.
Também é possível obter rapidamente o AuthenticationManager padrão por meio do AuthenticationManagerBuilder
AuthenticationProvider
O AuthenticationProvider implementa a lógica de autenticação e delega o gerenciamento de usuários e senhas às interfaces UserDetailsService e PasswordEncoder, ambas definidas na classe de configuração do projeto.
UserDetailService
A interface UserDetailsService possui um único método que deve ser implementado conforme a lógica do sistema e retornar um objeto que implementa a interface UserDetails
UserDetails
É a interface UserDetails que provê ao sistema as informações básicas sobre os usuários. Implementações dessa interface guardam informações que serão posteriormente encapsuladas em objeto que implementa a interface Authentication.
Essas implementações não são usadas diretamente pelo Spring para fins de segurança, o que permite que outras informações não relacionadas à segurança (telefone, email, etc.) sejam concentradas no mesmo lugar.
Password Encoder
A interface PasswordEncoder possui dois métdodos abstratos, encode e matches, que são autoexplicativos:
SecurityContext
É no SecurityContextHolder que o Spring guarda os detalhes de quem está autenticado:
Os relacionamentos entre as interfaces e classes que participam do processo de autenticação são os seguintes:
pom.xml
Para adicionar o Spring Security no seu projeto Spring Boot, adicione a seguinte dependência no arquivo pom.xml ou o equivalente no Gradle:
<!-- Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Para ver uma implementação de autenticação e autorização por meio do Spring Security com usuários e senhas armazenados em um banco de dados, pode dar uma olhada no meu github: https://github.com/lmgbsb/jwt
Referências:
https://livebook.manning.com/book/spring-security-in-action/chapter-2/section-2-2?origin=product-toc
https://docs.spring.io/spring-security/site/docs/4.0.x/apidocs/org/springframework/security/config/annotation/authentication/builders/AuthenticationManagerBuilder.html
https://docs.spring.io/spring-security/site/docs/4.0.x/apidocs/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.html#authenticationManagerBean--
https://docs.spring.io/spring-security/site/docs/4.0.x/apidocs/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.html
https://docs.spring.io/spring-security/site/docs/current/reference/html5/#servlet-authentication-authentication
https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/core/userdetails/UserDetails.html
https://2darray.com/featured/spring-security-architecture-authentication/
https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/authentication/UsernamePasswordAuthenticationToken.html
https://spring.io/guides/topicals/spring-security-architecture
https://docs.spring.io/spring-security/site/docs/4.2.15.RELEASE/apidocs/org/springframework/security/authentication/AuthenticationManager.html
https://docs.spring.io/spring-security/site/docs/5.5.1/api/org/springframework/security/core/Authentication.html
https://docs.spring.io/spring-security/site/docs/current/reference/html5/#servlet-authentication-providermanager
https://docs.spring.io/spring-security/site/docs/4.2.3.RELEASE/apidocs/index.html?org/springframework/security/config/annotation/authentication/builders/AuthenticationManagerBuilder.html
https://livebook.manning.com/book/spring-security-in-action/chapter-5/59
https://docs.spring.io/spring-security/site/docs/3.2.x/apidocs/org/springframework/security/core/userdetails/UserDetailsService.html
https://www.javadevjournal.com/spring-security/spring-security-authentication/
https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/core/userdetails/UserDetails.html
https://livebook.manning.com/concept/spring/userdetails-contract
https://en.wikipedia.org/wiki/Decorator_pattern
https://docs.spring.io/spring-security/site/docs/5.0.0.M5/api/org/springframework/security/crypto/password/PasswordEncoder.html
https://waynestalk.com/en/spring-security-architecture-explained-en/
https://ducmanhphan.github.io/2019-02-09-The-mechanism-of-spring-security/