Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

[Dúvida] [Dúvida] Alguem me de uma luz aqui por favor

Esse metodo da classe controller tem o UsernamePasswordAuthenticationToken que recebe o dados.login e o dados.senha, dentro do construtor do UsernamePasswordAuthenticationToken o this.principal recebe o login e o this.credencial recebe a senha, ne? Então o authentication.getPrincipal devolve o login em String convertendo para User é isso?Entao esse User nao tem senha? Onde é que ta ocorrendo a comparação entre os o RequestBody e os dados do banco de dados?

@PostMapping
   public ResponseEntity efetuarlogin(@RequestBody @Valid DadosAutenticacao dados){
      var authenticationToken = new UsernamePasswordAuthenticationToken(dados.login(), dados.senha());
      var authentication = manager.authenticate(authenticationToken);
      var token = tokenService.gerarToken((User) authentication.getPrincipal());

      return ResponseEntity.ok(new DadosToken(token));
   }

Para que serviu essa classe? em especifico esse metodo que devolver um UserDetails, o que seria esse UserDetails, e quando que devo ultilizar esse metodo?

@Service
public class AutenticacaoService implements UserDetailsService {

   @Autowired
   private UserRepository repository;

   @Override
   public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
      return repository.findByLogin(username);
   }

E esses dois metodos tbm da classe SecurityConfiguration servem pra que??

@Bean
   public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
      return configuration.getAuthenticationManager();
   }
   
@Bean
   public PasswordEncoder passwordEncoder() {
      return new BCryptPasswordEncoder();
   }

att: a dica que dou para quem teve a mesma duvida e quer entender como funciona por debaixo dos panos seria fazer o curso de Java Servlet: autenticação, autorização e o padrão MVC antes de entrar nessa de Spring boot para poder entender melhor o que estamos fazendo.

2 respostas
solução!

Oi Luccas!

Quase todo o processo de autenticação/autorização é feito pelo Spring Security por baixo dos panos, e justamente por isso acabam surgindo essas dúvidas mesmo que você mencionou. Vou te explicar todo o passo a passo de como funciona o processo:

O controller de autenticação não é do Spring e sim "nosso". Nele, implementamos a lógica que recebe a requisição contendo o username/password do usuário e inicia o processo de autenticação. Essa é a linha que inicia todo o processo de autenticação:

manager.authenticate(authenticationToken);

Essa linha chama o método authenticate da classe do Spring AuthenticationManager. Para isso, é necessário injetar no controller essa classe do Spring. Por mais que seja uma classe do próprio Spring, essa em específico ele não sabe como injetar sozinho e precisamos ensinar a ele como fazer a injeção. Isso a gente fez na nossa classe SecurityConfigurations:

@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
  return configuration.getAuthenticationManager();
}

Esse método anterior serve para ensinar ao Spring como ele deve fazer para criar um objeto do tipo AuthenticationManager, sempre que precisar injetá-lo em alguma classe.

Quando chamamos o método manager.authenticate(authenticationToken); o que o Spring faz, por baixo dos panos, é procurar nas configurações do nosso projeto como ele deve realizar o processo de autenticação. Ele vai detectar que temos uma classe que implementa a sua interface UserDetailsService e então chamará automaticamente o método loadUserByUsername dela, passando como parâmetro o username:

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    return repository.findByLogin(username);
}

Nesse método, implementamos como deve ser feita a lógica de verificar se o username enviado na requisição está válido. Mas e a senha? Não basta apenas checar se o username existe no banco de dados, precisamos checar se a senha está correta também! A verificação da senha é feita por baixo dos panos pelo Spring.

Repare que o método anterior devolve um objeto do tipo UserDetails, que é uma interface que tivemos que implementar em nossa classe Usuario e nela fomos obrigados a implementar vários métodos dessa interface, dentre eles o método getPassword, que devolve a senha do usuário.

Após chamar o método loadUserByUsername, o Spring faz a checagem da senha, mas agora temos uma outra questão: A senha que vem da requisição está em texto aberto (ex: 123456), mas a senha que veio do banco de dados, e está setada no objeto UserDetails, está no formato BCrypt. Como o Spring sabe que deve converter a senha de texto aberto para o formato BCrypt antes de realizar a comparação? Novamente, ele vai procurar em nosso projeto qual o PasswordEncoder que deve utilizar, e vai encontar isso na classe SecurityConfigurations:

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

Pronto! A comparacação será realizada e se a senha estiver certa, significa que a autenticação foi realizada com sucesso. Caso contrário, vai lançar uma exception.

O código então retorna ao método de autenticação de nosso controller:

var authentication = manager.authenticate(authenticationToken);

Repare que a chamada ao método manager.authenticate(authenticationToken); devolve um objeto do Spring que contém os dados do usuário autenticado. Caso o username ou senha estejam inválidos, não terá nenhum retorno, pois será lançada uma exception e o código será interrompido.

A partir desse ponto, é possível utilizar esse objeto devolvido pelo método authenticate para se obter o username, password, perfis e quaisquer outras informações referentes ao usuário que acabou de se autenticar.

Perceba como todas as configurações que fizemos no projeto, em relação ao Spring Security, tem um propósito e se encaixam perfeitamente no processo de autenticação do Spring. Porém, como ele faz 90% do trabalho por baixo dos panos, não fica tão obvio de entender como esse processo funciona.

Espero que tenha te ajudado a entender melhor o processo de autenticação do Spring Security.

Bons estudos!

Seria muito útil se essa explicação estivesse no curso, acompanhada de um fluxograma desse processo.