Implementei os códigos para agendamento de consultas. O projeto rodou. Porém, no Insomnia, apenas a requisição "Agendar Consulta" é rejeitada (403 Forbiden), as outras funcionam normalmente.
Implementei os códigos para agendamento de consultas. O projeto rodou. Porém, no Insomnia, apenas a requisição "Agendar Consulta" é rejeitada (403 Forbiden), as outras funcionam normalmente.
Oi!
No seu controller tem um system.out imprimindo os dados da requisição. Esse texto apareceu no console?
Bom dia professor.
No console não apareceu o texto da requisição. Apenas os system.out do filtro, que eu mantive do curso anterior.
Ok. Manda aqui suas classes SecurityFilter
e SecurityConfigurations
@Component
public class SecurityFilter extends OncePerRequestFilter{
@Autowired
private TokenService tokenService;
//para injetar o repository neste filtro, para permitir uma consulta no BD
@Autowired
private UsuarioRepository repository;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException
{
//varíável que recebe o token a partir de um método que extrai o token
var tokenJWT = recuperarToken(request);
//System.out.println(tokenJWT);
System.out.println("FILTRO SENDO CHAMADO!!!!");
/*
* Valida, se existir, o token e recupera o seu subject
*/
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);
System.out.println("LOGADO NA REQUISIÇÃO");
}
/*
* para verificar se recuperou o subject do token
*/
// System.out.println(subject);
/*
* para chamar o próximo filtro, encaminhando o request e o response
*/
filterChain.doFilter(request, response);
}
private String recuperarToken(HttpServletRequest request) {
var authorizationHeader = request.getHeader("Authorization");
//se existe o cabeçalho
if (authorizationHeader!=null){
return authorizationHeader.replace("Bearer ", "");
}
return null;
}
}
/*
* como é uma classe de configurações, usamos a anotação @Configuration
* dessa forma o Spring irá carregar essa classe no projeto
*/
@Configuration
/*
* como vamos personalizar o processo de autenticação e de autorização
* precisamos da anotação @EnableWebSecurity
*/
@EnableWebSecurity
public class SecurityConfiguration {
//para injetar a classe SecurityFilter
@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();
})
.addFilterBefore(securityFilter, UsernamePasswordAuthenticationFilter.class)
.build();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception{
return configuration.getAuthenticationManager();
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
@Configuration /*
como vamos personalizar o processo de autenticação e de autorização
precisamos da anotação @EnableWebSecurity */ @EnableWebSecurity public class SecurityConfiguration {
//para injetar a classe SecurityFilter @Autowired private SecurityFilter securityFilter;
/*
@Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception{ return configuration.getAuthenticationManager(); }
@Bean public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); }
}
Acho que deu problema no envio dessas classes.
Deve ser algum outro erro que está acontecendo, mas o Spring Security captura e devolve erro 403.
Altera a sua classe de tratamento de erros para tratar mais erros, conforme essa atividade: https://cursos.alura.com.br/course/spring-boot-aplique-boas-praticas-proteja-api-rest/task/125341
Dispare a requisição e veja no console e no retorno se mudou o erro.
Adicionei os outros métodos para tratamento de erros, mas não houve mudança no retorno.
@RestControllerAdvice public class TratadorDeErros{ //método para lidar com a Exception: EntityNotFoundException @ExceptionHandler(EntityNotFoundException.class) public ResponseEntity tratarErro404(){ return ResponseEntity.notFound().build(); //o build é para que ele crie o objeto ResponseEntity }
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity tratarErro400(MethodArgumentNotValidException ex){
var erros = ex.getFieldErrors();
return ResponseEntity.badRequest().body(erros.stream().map(DadosErroValidacao::new).toList());
}
@ExceptionHandler(HttpMessageNotReadableException.class)
public ResponseEntity tratarErro400(HttpMessageNotReadableException ex) {
return ResponseEntity.badRequest().body(ex.getMessage());
}
@ExceptionHandler(BadCredentialsException.class)
public ResponseEntity tratarErroBadCredentials() {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Credenciais inválidas");
}
@ExceptionHandler(AuthenticationException.class)
public ResponseEntity tratarErroAuthentication() {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Falha na autenticação");
}
@ExceptionHandler(AccessDeniedException.class)
public ResponseEntity tratarErroAcessoNegado() {
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("Acesso negado");
}
@ExceptionHandler(Exception.class)
public ResponseEntity tratarErro500(Exception ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Erro: " +ex.getLocalizedMessage());
}
//DTO que retorna apenas os campos que desejamos, em caso de erro de validação
private record DadosErroValidacao(String campo, String mensagem){
public DadosErroValidacao(FieldError erro){
//chama o construtor padrão do DTO, passando o campo e a mensagem de erro
this(erro.getField(), erro.getDefaultMessage());
}
}
}
Consegue compartilhar o teu projeto?
Professor, veja se consegue acessar:
https://github.com/benedditto/AgendamentoConsulta/tree/main/MedVoll
No seu projeto, no pacote controller. você criou uma anotação chamada @RestController
. Apague esse arquivo e no ConsultaController importe essa anotação do Spring.
Opa, deu certo professor. Muito obrigado.