Spring 引导从异常处理程序返回 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 之类的异常:由于服务器身份验证无法重试,在流媒体模式下。
ResponseEntity<String> responseEntity =
restTemplate.exchange(
this.validateTokenUrl,
HttpMethod.POST,
requestHttpEntity,
String.class);
但是如果我将 HttpStatus
从 ExceptionHandler
更改为 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);
查看此 link 了解更多详情:https://github.com/spring-projects/spring-security-oauth/issues/441#issuecomment-92033542
我有一个 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 之类的异常:由于服务器身份验证无法重试,在流媒体模式下。
ResponseEntity<String> responseEntity =
restTemplate.exchange(
this.validateTokenUrl,
HttpMethod.POST,
requestHttpEntity,
String.class);
但是如果我将 HttpStatus
从 ExceptionHandler
更改为 except HttpStatus.UNAUTHORIZED
我可以从客户端获得真正的 ApiError
对象。是什么导致了这个问题,我该如何解决?
编辑:创建了一个 github repo 来模仿我项目中有问题的部分。
默认情况下 RestTemplate
使用 DefaultResponseErrorHandler
。每当从 REST API.
如果您想要自定义错误处理,只需通过 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);
查看此 link 了解更多详情:https://github.com/spring-projects/spring-security-oauth/issues/441#issuecomment-92033542