为什么 Spring RestTemplate 的 401 响应被编辑(包含[无正文])?以及如何绕过它?

问题描述 投票:0回答:1

背景: 作为 API 请求周期的一部分,例如,对于 OTP 验证,我们调用外部 API (xxxx.com),如果 OTP 无效,则返回 401,同时带有 JSON 响应。

我们使用 Spring 的 RestTemplate 对 xxxx.com 进行外部调用,我们希望将 401 响应捕获为 Java 对象,但我们未能做到这一点。我们看到回复已被编辑。

我们使用的 RestTemplate 来自 JAR

org.springframework:spring-web:6.1.5

拨打电话的线路:

this.restTemplate.exchange("https://xxxx.com", HttpMethod.PUT, entity, responseType);

我们如何捕获非 2XX:

catch (HttpClientErrorException e) {
    if (successfulHttpStatuses.contains(e.getStatusCode())) {
        return e.getResponseBodyAs(responseType);
    } else {
        log.error("{} returned a {} status - {}", clientName, e.getStatusCode(), e.getMessage());
        throw e;
    }

我们的客户端完美适用于 2XX,只是在 401 期间,我们得到日志,

XXXClient returned a 401 status - [no body]

正如我们所期望的那样,“有一个身体”。 请看这个:

Image Showing the request, via Postman, returning a response on 401 此外,我们提到的外部 xxxx.com 使用承载身份验证,并针对无效的 JWT 抛出 401。

Response headers don't contain 所以,我相信这是一个经过深思熟虑的设计决定,出于安全原因屏蔽 401 响应。对于这种情况有解决办法吗?

java spring http resttemplate http-status-code-401
1个回答
0
投票

@Test public void unauthorizedRequestWithBodyTest() { this.server .expect(ExpectedCount.once(), requestTo("/unauthorized")) .andExpect(method(HttpMethod.PUT)) .andRespond(withStatus(HttpStatus.UNAUTHORIZED).body( " { \"message\" : \"Something is broken\", \"status\": \"401\" } ")); try { restTemplate.exchange("unauthorized", HttpMethod.PUT, null, String.class); } catch (HttpClientErrorException e) { System.out.println("Response with body content:"); System.out.printf("%s returned a %s status - %s\n\n", "clientName", e.getStatusCode(), e.getResponseBodyAsString()); } } @Test public void unauthorizedRequestWithoutBodyTest() { this.server .expect(ExpectedCount.once(), requestTo("/unauthorized")) .andExpect(method(HttpMethod.PUT)) .andRespond(withStatus(HttpStatus.UNAUTHORIZED)); try { restTemplate.exchange("unauthorized", HttpMethod.PUT, null, String.class); } catch (HttpClientErrorException e) { System.out.println("Response without body content:"); System.out.printf("%s returned a %s status - %s\n", "clientName", e.getStatusCode(), e.getMessage()); System.out.printf("%s returned a %s status - %s\n\n", "clientName", e.getStatusCode(), e.getResponseBodyAsString()); } }

输出如下:

Response with body content: clientName returned a 401 UNAUTHORIZED status - { "message" : "Something is broken", "status": "401" } Response without body content: clientName returned a 401 UNAUTHORIZED status - 401 Unauthorized: [no body] clientName returned a 401 UNAUTHORIZED status -

从实现中您可以看到,当responseBody为空时,
getErrorMessage()

方法返回

[no body]
文本
if (ObjectUtils.isEmpty(responseBody)) {
    return preface + "[no body]";
}

org.springframework.web.client.DefaultResponseErrorHandler#getErrorMessage

© www.soinside.com 2019 - 2024. All rights reserved.