4
respostas

Erro 403 tentando fazer login!

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

@Service
public class TokenService {

    @Value("${api.security.token.secret}")
    private String secret;

    public String gerarToken(Usuario usuario) {
        try {
            var algoritmo = Algorithm.HMAC256(secret);
            return JWT.create()
                    .withIssuer("API Voll.med")
                    .withSubject(usuario.getLogin())
                    .withExpiresAt(dataExpiracao())
                    .sign(algoritmo);
        } catch (JWTCreationException exception){
            throw new RuntimeException("erro ao gerar token jwt", exception);
        }
    }

    public String getSubject(String tokenJWT) {
        try {
            var algoritmo = Algorithm.HMAC256(secret);
            return JWT.require(algoritmo)
                    .withIssuer("API Voll.med")
                    .build()
                    .verify(tokenJWT)
                    .getSubject();
        } catch (JWTVerificationException exception) {
            throw new RuntimeException("Token JWT inválido ou expirado!");
        }
    }

    private Instant dataExpiracao() {
        return LocalDateTime.now().plusHours(2).toInstant(ZoneOffset.of("-03:00"));
    }

}
@Component
public class SecurityFilter extends OncePerRequestFilter {

    @Autowired
    private TokenService tokenService;

    @Autowired
    private UsuarioRepository repository;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        var tokenJWT = recuperarToken(request);

        if (tokenJWT != null) {
            var subject = tokenService.getSubject(tokenJWT);
            var usuario = repository.findByLogin(subject);

            var authentication = new UsernamePasswordAuthenticationToken(usuario, null, usuario.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }

        filterChain.doFilter(request, response);
    }

    private String recuperarToken(HttpServletRequest request) {
        var authorizationHeader = request.getHeader("Authorization");
        if (authorizationHeader != null) {
            return authorizationHeader.replace("Bearer ", "");
        }

        return null;
    }

}
@Configuration
@EnableWebSecurity
public class SecurityConfigurations {

    @Autowired
    private SecurityFilter securityFilter;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return
                http.csrf(csrf -> csrf.disable())
                        .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                        .authorizeHttpRequests(req -> {
                            req.requestMatchers("/login").permitAll();
                            req.anyRequest().authenticated();
                        })
                        .build();
    }

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

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
@RestController
@RequestMapping("/login")
public class AutenticacaoController {

    @Autowired
    private AuthenticationManager manager;

    @Autowired
    private TokenService tokenService;

    @PostMapping
    public ResponseEntity efetuarLogin(@RequestBody @Valid DadosAutenticacao dados) {
        var authenticationToken = new UsernamePasswordAuthenticationToken(dados.login(), dados.senha());
        var authentication = manager.authenticate(authenticationToken);

        var tokenJWT = tokenService.gerarToken((Usuario) authentication.getPrincipal());

        return ResponseEntity.ok(new DadosTokenJWT(tokenJWT));
    }

}
4 respostas

Olá Gabriel! Tudo bem?

Analisando os trechos de código que você compartilhou, não consegui identificar nenhuma inconsistência que poderia estar levando um 403, como mostrado no seu print. Um erro 403 está relacionado a autenticação do usuário, tem certeza que estava acessando a rota de login e não outra que precisaria de um token para ser acessada?

No mais, preciso que compartilhe comigo todo o seu projeto para que eu possa testar a fim de identificar o que está causando essa situação. Envie usando o GitHub ou Drive do Google.

Fico no aguardo e à disposição

Meu github: https://github.com/gabrieltizziani/Vollmed_api

Boa tarde, Gabriel!

Testei a sua rota login e ela funcionou corretamente, mas imagino que você estava testando outra rota e não a de login já que o erro que aparece no seu terminal está relacionado ao Token de acesso que está inspirado.

Esse Token é gerado toda vez que você realiza login e o mesmo deve ser passado no campo Bearer Token da requisição para autorizar a chamado dos métodos da API. Mas esses Tokens tem um tempo de duração e o que você estava usando aparentemente inspirou, execute o login novamente para coletar outro Token.

Mas, mesmo fazendo isso na sua aplicação, ela estava retornando erro 403 no Insomnia. Então, ao analisar o seu arquivo SecurityConfigurations percebi que estava faltando o filtro .addFilterBefore(securityFilter, UsernamePasswordAuthenticationFilter.class) antes do build do securityFilterChain desse arquivo, e isso estava causando o erro.

Logo, para o problema com erro 403, basta adicionar esse filtro, segue o código do arquivo SecurityConfigurations com o filtro aplicado:

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return
                http.csrf(csrf -> csrf.disable())
                        .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                        .authorizeHttpRequests(req -> {
                            req.requestMatchers("/login").permitAll();
                            req.anyRequest().authenticated();
                        })
                        .addFilterBefore(securityFilter, UsernamePasswordAuthenticationFilter.class)
                        .build();
    }

Espero que agora sua API rode sem mais problemas!

Muito obrigado, funcionou certinho!