簡體   English   中英

Spring Boot 從異常處理程序返回 401 狀態的自定義對象

[英]Spring Boot Returning 401 Statused Custom Object From Exception Handler

我有一個 Spring Boot rest API,它有一個 LoginController 用於執行簡單的身份驗證過程。 這是令牌驗證操作。

@PostMapping("validatetoken")
public ResponseEntity<ValidateTokenResponse> validateToken(
        @RequestBody ValidateTokenRequest validateTokenRequest, HttpServletRequest request) throws Exception {

    if (StringUtils.isEmpty(validateTokenRequest.getToken())) throw new AuthenticationFailedException("token parameter cannot be null or empty");

    Boolean isValid = authenticationService.validateToken(request, validateTokenRequest.getToken());
    ValidateTokenResponse response = new ValidateTokenResponse();
    response.setIsValid(isValid);
    response.setToken(validateTokenRequest.getToken());
    return new ResponseEntity<>(response, isValid? HttpStatus.OK : HttpStatus.UNAUTHORIZED);
}

在我的 api 中,我在ResponseEntityExceptionHandler捕獲所有錯誤並以這種方式轉換自定義對象。

@ExceptionHandler(AuthenticationFailedException.class)
@ResponseBody
protected ResponseEntity<Object> handleAuthenticationFailed(AuthenticationFailedException ex) {
    LogManager.error(ex);
    ApiError apiError = new ApiError(HttpStatus.UNAUTHORIZED);
    apiError.setMessage(ex.getMessage());
    return buildResponseEntity(apiError);
}

但是,當我想使用如下所示的RestTemplate調用此 api 時,我收到了類似java.net.HttpRetryException: cannot retry due to server authentication, in streaming mode 的異常。

ResponseEntity<String> responseEntity =
    restTemplate.exchange(
        this.validateTokenUrl,
        HttpMethod.POST,
        requestHttpEntity,
        String.class);

但是如果我將HttpStatusExceptionHandler更改為 except HttpStatus.UNAUTHORIZED我可以從客戶端獲取真正的ApiError對象。 什么可能導致此問題,我該如何解決?

編輯:創建了一個github repo來模仿我項目中的問題部分。

默認情況下, RestTemplate使用DefaultResponseErrorHandler 每當從REST API發送4xx / 5xx響應時,此錯誤處理程序就會引發異常。

如果要自定義錯誤處理,只需通過restTemplate.setErrorHandler注冊您的自定義錯誤處理程序,即可在其中使用ResponseErrorHandler接口的實現。

為了清楚起見,我建議將帶有以下詳細信息的resttemplate自動連接到單獨的配置文件中

@Bean
  public RestTemplate restTemplate() {
    RestTemplate restTemplate = new RestTemplate();
    restTemplate.setErrorHandler(new ErrorHandler());

    SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
    requestFactory.setOutputStreaming(false);

    restTemplate.setRequestFactory(requestFactory);

    return restTemplate;
  }

這是 SimpleClientHttpRequestFactory 的默認行為(使用 JDK 的內部 http 客戶端)

一個簡單的解決方法是使用 apache http 組件庫:

ClientHttpRequestFactory  requestFactory = new HttpComponentsClientHttpRequestFactory();
restTemplate.setRequestFactory(requestFactory);

有關更多詳細信息,請參閱此鏈接: https : //github.com/spring-projects/spring-security-oauth/issues/441#issuecomment-92033542

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM