Olá, Leonardo!
Entendo a sua frustração com o UsernamePasswordAuthenticationFilter retornando um erro 403 antes de passar pelo seu TratadorDeErros. Isso acontece porque o filtro de autenticação é executado antes do controlador, e, portanto, antes do seu tratador de erros personalizado.
Para contornar esse problema, você pode implementar um AuthenticationEntryPoint personalizado. O AuthenticationEntryPoint é responsável por iniciar o processo de autenticação quando uma solicitação não autenticada tenta acessar um recurso protegido. Ao criar um EntryPoint personalizado, você pode manipular a resposta de erro antes de ser enviada ao cliente.
Aqui está um exemplo de como você pode fazer isso:
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Acesso negado! Você não tem permissão para acessar este recurso.");
}
}
Depois de criar o EntryPoint personalizado, você precisa configurá-lo na sua classe de configuração de segurança:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@EnableWebSecurity
@Configuration
public class SecurityConfigurations {
@Autowired
private CustomAuthenticationEntryPoint customAuthenticationEntryPoint;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// configs atuais...
.and()
.exceptionHandling().authenticationEntryPoint(customAuthenticationEntryPoint);
}
}
Com isso, o seu CustomAuthenticationEntryPoint será chamado quando uma tentativa de acesso não autorizada ocorrer, permitindo que você controle a resposta de erro.
Espero ter ajudado e bons estudos!