当前位置: 首页 > 知识库问答 >
问题:

java.net.HttpRetryExc0019:无法重试由于服务器身份验证,在流模式

潘胤
2023-03-14

我们的应用程序中有两个部分:
服务器-提供REST服务
客户端-通过Spring restTemplate使用它们

除了HTTP状态之外,我们的服务器还返回一个包含JSON的HTTP正文,详细描述了错误。所以,我在restTemplate中添加了自定义错误处理程序,以将一些编码为非错误的错误处理——这有助于很好地解析HTTP正文。

但在HTTP/1.1 401未经授权的情况下,我通过解析HTTP主体得到了一个异常。所有其他错误代码都得到了很好的处理(400、402等)。我们使用普通服务器逻辑,在发生错误时发送HTTP响应,对于不同类型的错误没有特殊规则:

writeErrorToResponse(int status, String errMsg, HttpServletResponse resp) throws IOException {
        response.setStatus(status);
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        String message = String.format("{\"error\":\"%s\"}", StringUtils.escapeJson(errMsg));
        resp.getWriter().println(message);
    }

但是在客户端只有HTTP/1.1 401抛出异常-"java.net.HttpRetryExcture:无法重试由于服务器身份验证,在流模式"

我进行了一些调试,发现问题的原因是SimpleClientHttpResponse中的代码:

HttpURLConnection。getInputStream()

使用Fiddler进行跟踪会有以下响应:在客户端上正确解析消息:

HTTP/1.1 402 Payment Required
X-Powered-By: Servlet/3.0
Content-Type: application/json
Content-Language: en-GB
Content-Length: 55
Connection: Close
Date: Sat, 25 May 2013 10:10:44 GMT
Server: WebSphere Application Server/8.0

{"error":"I cant find that user.  Please try again."}

以及导致异常的消息

HTTP/1.1 401 Unauthorized
X-Powered-By: Servlet/3.0
Content-Type: application/json
Content-Language: en-GB
Content-Length: 55
Date: Sat, 25 May 2013 11:00:21 GMT
Server: WebSphere Application Server/8.0

{"error":"I cant find that user.  Please try again."}

在这种情况下,java.net.HttpRetryExcure的原因是什么?

此外:前几次,这种机制运行良好。但自从我们在应用程序中更改了很多代码之后。

共有3个答案

葛高澹
2023-03-14

我在使用Spring Boot 2.2.4和TestRest模板时遇到了完全相同的问题。它只在401上失败了。只需在测试范围内添加最新版本的Http客户端(4.5.11)就可以解决这个问题。无需进一步配置。

徐奇
2023-03-14

这个问题在Spring框架中进行了报道。

参考:https://jira.spring.io/browse/SPR-9367

从引用复制:使用默认设置在RestTemplate中处理401响应非常困难(不可能)。事实上这是可能的,但您必须提供一个错误处理程序和一个请求工厂。错误处理程序很明显,但问题是默认的请求工厂使用java。net,当您试图查看响应的状态代码时(尽管它显然可用),它会抛出HttpRetryException。解决方案是使用HttpComponents客户端HttpRequestFactory。例如。

template.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
template.setErrorHandler(new DefaultResponseErrorHandler() {
    public boolean hasError(ClientHttpResponse response) throws IOException {
        HttpStatus statusCode = response.getStatusCode();
        return statusCode.series() == HttpStatus.Series.SERVER_ERROR;
    }
});
<dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
</dependency>
帅锦
2023-03-14

在使用SimpleClientHttpRequestFactory时,我也遇到了同样的问题。通过设置

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

这个问题是由于在进行身份验证时的分块和后续重试机制造成的。

您还可以使用HttpClient策略禁用块

 类似资料:
  • 问题内容: 为服务器端路由验证用户的最佳方法(最安全,最简单)是什么? 软件/版本 我使用的是最新的Iron Router 1. 和Meteor 1. ,首先,我使用的是Accounts-password。 参考代码 我有一个简单的服务器端路由,可将pdf呈现到屏幕上: 两者/routes.js 举例来说,我想做些类似于该SO答案建议的操作: 在服务器上: 然后在客户端代码中: 但是,即使我以某种

  • 出身背景我需要让我的网站通过IdentityServer(IDS)进行身份验证。“example.com” 我正在用DotNetCore构建我所有的网站,用apache在代理服务器上托管它们,让我们调用私有ip12.3.4.5。 它们应该如何工作。我去网站的例子。我应该可以和ids通话。例如。com获取身份验证信息,然后重新路由回示例。具有身份验证令牌的com。相反,我得到了一个SSL握手错误。见

  • 我想测试一个WSO2身份提供程序,实际上是它用OpenID配置的联合IdP,我计划使用TraSpeed工具对其进行测试。我正在WEB-INF配置中编辑travelocity.properties文件,将起始参数设置为以下值: 在Tomcat7服务器中声明映像时,它接受新的服务器配置,但代码仍将SAML身份验证激活为主要SSO机制,抛出错误: 是否可以仅使用OpenID堆栈在该Web工具中停用SAM

  • 它总是导致带有错误消息的catch块 登录失败:未知的用户名或错误的密码。失败:未知的用户名或错误的密码。 我确信给定的密码是正确的。 如何使用给定的密码验证用户名?

  • 我正在构建一个自定义移动应用程序,它有一个客户端,自定义后端服务器(我正在构建),并与许多其他API交互。其中一个API是Microsoft Bookings。 我面临的问题是,我需要通过服务器对服务器进行身份验证,并使用共享的客户端秘密。我知道多发性硬化症有很多医生,但还没有找到解决办法。我想知道服务器到服务器是否可以预订。 我能够获得一个access_token服务器到具有这些权限的服务器。(

  • 将配置服务器用户名和密码存储为环境变量(在客户端和服务器中)还是使用密钥库更好?密钥库密码无论如何都存储为环境变量,那么为什么实际使用密钥库呢?还是有更好的方法在SpringCloudConfig服务器中实现身份验证?