6
respostas

[Projeto] Mesmo com o token, recebo um código 403 Forbidden

Mesmo com o token, tendo realizar um cadastro médico pelo postman, mas recebo a mensagem 403 Forbidden.

Tenho de configurar algo mais além do Autorization do postman ?

6 respostas

Oi Anderson!

Tem algum erro no seu projeto então. Posta aqui as classes para avaliarmos.

DadosTokenJWT: package med.voll.api.infra.security;

public record DadosTokenJWT(String token) { }

SecurityConfigurations: package med.voll.api.infra.security;

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration @EnableWebSecurity public class SecurityConfigurations {

@Autowired
private SecurityFilter securityFilter;

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

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

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

}

SecurityFilter: package med.voll.api.infra.security;

import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import med.voll.api.domain.usuario.UsuarioRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

@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 autentication = new UsernamePasswordAuthenticationToken(usuario,null,usuario.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(autentication);
    }

    //Chama o próximo filtro
    filterChain.doFilter(request,response);

}

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

    return null;
}

}

TokenService: package med.voll.api.infra.security;

import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTCreationException; import com.auth0.jwt.exceptions.JWTVerificationException; import med.voll.api.domain.usuario.Usuario; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service;

import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.util.Date;

@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"));
}

}

AutenticacaoController: package med.voll.api.controller;

import jakarta.validation.Valid; import med.voll.api.domain.usuario.DadosAutenticacao; import med.voll.api.domain.usuario.Usuario; import med.voll.api.infra.security.DadosTokenJWT; import med.voll.api.infra.security.TokenService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;

@RestController @RequestMapping("/login") public class AutenticacaoController {

@Autowired
private AuthenticationManager manager;

@Autowired
private TokenService tokenService;

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

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

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

}

O engraçado é quer as consultas funcionam, mas quando troco o verbo GEt pelo POST ou PUT, ganho o 403.

Por isso, achei que fosse alguma coisa de configuração no Postman

Mestre, pode esquecer. Está funcionando direito. Era erro no json de entrada no cadastro. Tinha um dado repetido. Vou melhorar o tratamento de erro. A mensagem está errada nesse caso.

Obrigado.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software