Spring Web оборачивает любые ошибки в 403 статусный код

Я пытаюсь написать микросервисный проект используя spring boot версии 3.4.5. Проблема возникла при добавлении в spring security необходимость быть авторизованным. Любая ошибка будет провоцировать возврат 403 кода. Даже встроенные в spring ошибки, по типу method not allowed или несуществующего endpoint вместо 405 и 404 соответственно вернут 403. Сейчас мой конфиг выглядит так:

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@RequiredArgsConstructor
public class SecurityConfig {

    private final AuthFeign authFeign;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf(AbstractHttpConfigurer::disable)
                .cors(AbstractHttpConfigurer::disable)
                .sessionManagement(smc -> smc.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers("/actuator/health", "/v3/api-docs").permitAll()
                        .anyRequest().authenticated()
                )
                .httpBasic(AbstractHttpConfigurer::disable)
                .addFilterBefore(jwtAuthenticationFilter(workWithJwt()), UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(apiKeyAuthFilter(), JwtAuthenticationFilter.class);


        return http.build();
    }

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

    @Bean
    public JwtAuthenticationFilter jwtAuthenticationFilter(WorkWithJwt workWithJwt) {
        return new JwtAuthenticationFilter(workWithJwt);
    }

    @Bean
    public ApiKeyAuthFilter apiKeyAuthFilter() {
        return new ApiKeyAuthFilter();
    }

    @Bean
    @Profile("dev")
    public WorkWithJwt workWithJwt() {
        return new WorkWithJwt(authFeign);
    }

}

Причем переключение с anyRequest().authenticated() на .permitAll() решает проблему. Собственно сам фильтр для jwt аутентификации:

public class JwtAuthenticationFilter extends OncePerRequestFilter {
    private final WorkWithJwt jwtUtil;

    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String authHeader = request.getHeader("Authorization");
        if (authHeader != null && authHeader.startsWith("Bearer ") && SecurityContextHolder.getContext().getAuthentication() == null) {
            String token = authHeader.substring(7);
            if (this.jwtUtil.validateToken(token)) {
                this.jwtUtil.parseClaims(token);
                UUID userId = this.jwtUtil.getUserIdFromToken(token);
                String email = this.jwtUtil.getEmailFromToken(token);
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(email, (Object)null, List.of(new SimpleGrantedAuthority("ROLE_USER")));
                authentication.setDetails(userId);
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }

        filterChain.doFilter(request, response);
    }

    @Generated
    public JwtAuthenticationFilter(final WorkWithJwt jwtUtil) {
        this.jwtUtil = jwtUtil;
    }
}

Причем пробовал еще и реализацию через AuthenticationProvider, ничего не поменялось. Для проверок сделал так, чтобы один из методов сервиса кидал runtimeException. Даже так вернется не 500, а 403 код. Проверял наличие Authentification в контексте, какие данные там вообще лежат - все правильно: есть и principal, и authenticated true, все вообще правильно. Из authentication получаются данные, они валидны, используются в сервисах при обращении в бд - все работает. В ControllerAdvice нет перехвата всех ошибок и преобразование их в 403.

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ResponseBody
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ValidationErrorResponse onConstraintValidationException(
            ConstraintViolationException ex
    ) {
        final List<Violation> violations = ex.getConstraintViolations().stream()
                .map(
                        violation -> {
                            Violation v = new Violation();
                            v.setMessage(violation.getMessage());
                            String[] s = violation.getPropertyPath().toString().split("\\.");
                            v.setFieldName(s[s.length - 1]);
                            return v;
                        }
                ).toList();
        return new ValidationErrorResponse(violations);
    }

    @ExceptionHandler(ServiceException.class)
    public ResponseEntity<String> exception(ServiceException e) {
        return new ResponseEntity<>(e.getMessage(), e.getHttpStatus());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<String> exception(MethodArgumentNotValidException e) {
        return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public ResponseEntity<String> exception(MethodArgumentTypeMismatchException e) {
        return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
    }

}

Кто-то может подсказать решение проблемы? Буду рад любой помощи, если нужны доп материалы выложу.


Ответы (0 шт):