java - 重用授权 header 以防止 Jersey Client 的多个 407 代理身份验证挑战

标签 java http apache-httpclient-4.x jersey-client proxy-authentication

我正在使用 Jersey Client 2.0 库(带有 Apache HttpClient v4.2.5 传输连接器)来使用 RESTful Web 服务。我的应用程序必须支持通过具有任何基本、摘要或 NTLM 身份验证的代理服务器进行连接。我添加了对所有这些类型的代理身份验证的支持,并且基本上一切正常。

这就是我添加对基本和摘要代理身份验证支持的方式:

ClientConfig config = new ClientConfig();
config.property(ApacheClientProperties.PROXY_URI, "http://www.proxy.com:5678");
config.property(ApacheClientProperties.PROXY_USERNAME, "proxy_user");
config.property(ApacheClientProperties.PROXY_PASSWORD, "proxy_password");
ApacheConnector connector = new ApacheConnector(config);
config.connector(connector);
Client client = ClientBuilder.newClient(config);

此外,我要连接的 RESTful Web 服务本身也需要基本身份验证,我使用以下方法处理:

client.register( new HttpBasicAuthFilter("user", "password") );

但是,我的应用程序的行为并不完全符合我的要求:似乎我发出的每个单独的 HTTP 请求都会导致来自代理服务器的 407 身份验证质询响应。这是一个问题,原因有二:

  1. 如果我使用由 InputStream,它被认为是一个“不可重复”的请求,所以当收到 407 挑战时,我得到以下异常:

    org.apache.http.client.NonRepeatableRequestException: Cannot retry request with a non-repeatable request entity.
    

    我可以通过将来自 InputStream 的实体主体数据缓冲到字符串或字节数组中来解决这个问题,以便在收到 407 质询时请求可重复,但这是低效的并且没有解决问题 2。

  2. 必须重复每个请求,首先触发 407 质询,然后使用必要的额外 HTTP header 重复进行代理身份验证,效率非常低。我的一些客户端操作涉及对 RESTful Web 服务的大量 HTTP 请求,因此这种额外的流量和延迟是不幸的。

我的期望是,一旦 Jersey 客户端第一次成功通过代理服务器的身份验证,使用同一 Client 实例发出的所有后续请求将自动包含必要的 Proxy-Authorization header 以防止任何进一步的 407 挑战。根据 this link,这似乎是 HTTP 1.1 的标准方法:

A proxy server sends the client a Proxy-Authenticate header, containing a challenge, in a 407 (Proxy Authentication Required) response. The client then repeats the initial request, but adds a Proxy-Authorization header that contains credentials appropriate to the challenge. After successful proxy authentication, a client typically sends the same Proxy-Authorization header to the proxy with each subsequent request, rather than wait to be challenged again.

所以我的问题是我需要将哪些配置设置应用到 Jersey Client 或底层 Apache HttpClient 传输层才能启用此行为?我已经看到各种其他帖子建议手动添加 Proxy-Authorization header ,但我宁愿尽可能避免这种解决方法。我也在理想地寻找一种解决方案,该解决方案适用于我正在使用的所有三种类型的代理身份验证(基本、摘要和 NTLM)。

如果无法阻止所有这些额外的 407 挑战,我还想推荐以“可重复”方式从本地文件发布或放置数据时的最佳方法,以防止 407 代理身份验证挑战后出现问题。

最佳答案

最后,我通过将我的项目升级到 Jersey Client v2.6 并将客户端配置为自动缓冲我的所有 POST/PUT 请求来解决问题 1,以便它们“可重复”以响应返回的任何 407 挑战来自代理服务器。

通过在 ClientConfig 上设置以下属性,可以在 Jersey Client v2.5+ 中启用请求缓冲对象,它将请求实体处理模式从“分块”(默认)更改为“缓冲”:

config.property(ClientProperties.REQUEST_ENTITY_PROCESSING,
                RequestEntityProcessing.BUFFERED);

这现在对我来说适用于我必须支持的所有三种类型的代理身份验证:基本、摘要和 NTLM。我只在用户配置了代理服务器时才启用这种“缓冲”模式,因为我认为除非绝对必要,否则最好坚持使用默认的“分块”模式。我担心在内存中缓冲大型 PUT/POST 请求的开销,以及不分块数据可能会降低效率。

现在我的客户端应用程序可以正常工作,但我仍然很想知道问题 2 的任何可能解决方案,因为最好只根据 Client 触发一个初始 407 代理身份验证质询。实例。由于摘要和 NTLM 身份验证固有的额外复杂性,我怀疑此问题的任何潜在解决方案都只能用于基本身份验证。

关于java - 重用授权 header 以防止 Jersey Client 的多个 407 代理身份验证挑战,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19681965/

相关文章:

java - Mockito 的参数捕捉器行为

perl - 如何从 Perl 发出 HTTP GET 请求?

来自 ffmpeg 的 Http Streaming,如何获取序列数据包?

java - 如何在 apache HTTPClient 中处理相对 URL

apache-httpclient-4.x - 从响应中理解 Apache HttpClient 线路日志

java - apache HttpClient API 中的 setConnectionTimeout 、 setSoTimeout 和 "http.connection-manager.timeout"有什么区别

java - In-App Billing v3 可靠性缺陷

java - 单击按钮时如何将数组添加到 Jtable java

java - JBoss 6 无法在装有 JDK 7 的 Windows(32 位)机器上启动

javascript - node.js 中未记录的 response.finished