Почему у меня не выводится ответ с ошибкой авторизации?

У меня есть авторизованный запрос

DELETE http://localhost:8080/api/v1/users/delete/1

Вот контроллер

@DeleteMapping("/delete/{id}")
    public ResponseEntity<UserResponseDTO> deleteUser(@PathVariable("id") Long id) {
        return ResponseEntity.ok(userService.delete(id));
    }

Он возвращает ответ

{
  "type": "about:blank",
  "title": "Forbidden",
  "status": 403,
  "detail": "An unexpected error occurred: Доступ запрещен",
  "instance": "/api/v1/users/delete/1"
}

Но когда я подкрепляю заголовок авторизации заведемо неверный

DELETE http://localhost:8080/api/v1/users/delete/1
Authorization:Basic YWRtaW5ADZXhhbXBsZS5jb206YWRtaW4= - неверный base64- строка

Вот какой ответ мне возвращается

DELETE http://localhost:8080/api/v1/users/delete/1
Authorization:Basic YWRtaW5ADZXhhbXBsZS5jb206YWRtaW4=
HTTP/1.1 200 
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
WWW-Authenticate: Basic realm="Realm"
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Length: 0
Date: Mon, 04 Nov 2024 10:05:56 GMT

<Response body is empty>

С верным заголовком все работает как надо Почему возращается пустое тело и код ответа 200 Если я убираю глобальный обработчик ошибок,то ничего не меняется. Возможно это связано с entryPoint?

Должен вернуться 401 / 403 и тело ответа с ошибкой

Почему у меня не обрабатывается ошибка ?

org.springframework.security.authentication.BadCredentialsException: Invalid basic authentication token
org.springframework.security.authentication.BadCredentialsException: Invalid basic authentication token
org.springframework.security.authentication.BadCredentialsException: Invalid basic authentication token

у меня есть глобальный обработчик ошибок

@RestControllerAdvice(basePackages = "ru.oniskovet.carsforum.controllers")
public class GlobalExceptionHandler  {

    @ExceptionHandler({IllegalArgumentException.class, NoSuchElementException.class, NoHandlerFoundException.class})
     ResponseEntity<ProblemDetail> handleNotFoundErrors(Exception e) {
        ProblemDetail problemDetail = ProblemDetail.forStatus(404);
        problemDetail.setTitle("Not found");
        problemDetail.setDetail("An unexpected error occurred: " + e.getLocalizedMessage());
        return ResponseEntity.status(404)
                .body(problemDetail);
    }



    @ExceptionHandler(MethodArgumentNotValidException.class)
     ResponseEntity<Object> handleMethodValidationException(Exception e) {
        ProblemDetail problemDetail = ProblemDetail.forStatus(400);
        problemDetail.setTitle("Validation Error");
        problemDetail.setDetail("An unexpected error occurred: " + e.getLocalizedMessage() );
        return ResponseEntity.badRequest()
                .body(problemDetail);
    }

    @ExceptionHandler({BadRequestException.class, MissingRequestValueException.class})
    ResponseEntity<Object> handleMethodClientException(Exception e) {
        ProblemDetail problemDetail = ProblemDetail.forStatus(400);
        problemDetail.setTitle("Validation Error");
        problemDetail.setDetail("An unexpected error occurred: " + e.getLocalizedMessage() );
        return ResponseEntity.badRequest()
                .body(problemDetail);
    }

    @ExceptionHandler({UsernameNotFoundException.class, BadCredentialsException.class})
    ResponseEntity<ProblemDetail> handleAuthenticationException(Exception e) {
        ProblemDetail problemDetail = ProblemDetail.forStatus(401);
        problemDetail.setTitle("unauthorized");
        problemDetail.setDetail("An unexpected error occurred: " + e.getLocalizedMessage() );
        return ResponseEntity.status(401)
                .body(problemDetail);
    }

    @ExceptionHandler(InsufficientAuthenticationException.class)
    ResponseEntity<ProblemDetail> handleInsufficientAuthenticationException(InsufficientAuthenticationException e) {
        ProblemDetail problemDetail = ProblemDetail.forStatus(401);
        problemDetail.setTitle("unauthorized");
        problemDetail.setDetail("An unexpected error occurred: " + e.getLocalizedMessage() );
        return ResponseEntity.status(401)
                .body(problemDetail);
    }

    @ExceptionHandler(AccountStatusException.class)
    ResponseEntity<ProblemDetail> handleAccountStatusException(AccountStatusException e) {
        ProblemDetail problemDetail = ProblemDetail.forStatus(401);
        problemDetail.setTitle("unauthorized");
        problemDetail.setDetail("An unexpected error occurred: " + e.getLocalizedMessage() );
        return ResponseEntity.status(401)
                .body(problemDetail);
    }



    @ExceptionHandler(AccessDeniedException.class)
    ResponseEntity<ProblemDetail> handleAccessDeniedException(AccessDeniedException e) {
        ProblemDetail problemDetail = ProblemDetail.forStatus(403);
        problemDetail.setTitle("Forbidden");
        problemDetail.setDetail("An unexpected error occurred: " + e.getLocalizedMessage() );
        return ResponseEntity.status(403)
                .body(problemDetail);
    }


     @ExceptionHandler(Exception.class)
     ResponseEntity<ProblemDetail> handleGenericExceptions(Exception e) {
        ProblemDetail problemDetail = ProblemDetail.forStatus(500);
        problemDetail.setTitle("Internal Server Error");
        problemDetail.setDetail("An unexpected error occurred: " + e.getLocalizedMessage());
        return ResponseEntity.status(500)
                .body(problemDetail);
    }
}

Вот мой конфиг безопасности

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class WebSecurityConfig {
    private UserDetailsService userDetailsService;
    private AuthenticationEntryPoint authenticationEntryPoint;

    @Autowired
    public WebSecurityConfig(UserDetailsService userDetailsService, AuthenticationEntryPoint authenticationEntryPoint) {
        this.userDetailsService = userDetailsService;
        this.authenticationEntryPoint = authenticationEntryPoint;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests((requests) -> requests
                        .anyRequest().permitAll()
                )
                .csrf().disable() // Отключаем CSRF защиту, так как для HTTP Basic её включать не нужно
                .sessionManagement(session -> session
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS) // Используем stateless сессии для Basic Auth
                )
                .authenticationProvider(authenticationProvider())
                .httpBasic()
                .authenticationEntryPoint(authenticationEntryPoint);

        return http.build();
    }

    @Bean
    public AuthenticationManager authenticationManagerBean(AuthenticationConfiguration authConfig) throws Exception {
        return authConfig.getAuthenticationManager();
    }


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

    @Bean
    public AuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setUserDetailsService(userDetailsService);
        provider.setPasswordEncoder(bCryptPasswordEncoder());
        return provider;
    }

}

Вот мой EntryPoint

@Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
    private final HandlerExceptionResolver resolver;

    public CustomAuthenticationEntryPoint(@Qualifier("handlerExceptionResolver") HandlerExceptionResolver resolver) {
        this.resolver = resolver;
    }

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)  {
        response.addHeader("WWW-Authenticate", "Basic realm=\"Realm\"");
        resolver.resolveException(request, response, null, authException);
    }
}

Авторизация у меня настроена через аннотации над методами сервисов

public interface UserService {
    @Secured("ROLE_ADMIN")
    UserResponseDTO delete(Long id);

    @PreAuthorize("hasRole('ROLE_ADMIN') or ((hasRole('ROLE_USER')" +
            "and @articleService.isHasAccessToArticle(authentication.principal.id, #id)))")
    UserResponseDTO update(Long id, UserRequestDTO user);

    @PermitAll
    UserResponseDTO getById(Long id);

    @PermitAll
    UserResponseDTO create(UserRequestDTO user);

    @PermitAll
    List<UserResponseDTO> getAll();

    @PermitAll
    List<UserResponseDTO> getALLByUsername(String username);

    User get(Long id);
}

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