我正在使用 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 身份验证质询响应。这是一个问题,原因有两个:
如果我使用 an 提供的实体主体发出
POST
orPUT
请求(已在上一个请求中成功通过代理服务器进行身份验证)InputStream
,则它被视为“不可重复”请求,因此当收到 407 质询时,我得到以下异常:org.apache.http.client.NonRepeatableRequestException: Cannot retry request with a non-repeatable request entity.
我可以通过将实体主体数据从 缓冲到字符串或字节数组中来解决此问题,
InputStream
以便在收到 407 质询时可以重复请求,但这效率低下并且不能解决问题 2。- 必须复制每个请求,首先触发 407 质询,然后重复必要的附加 HTTP 标头以进行代理身份验证,这是非常低效的。我的一些客户端操作涉及对 RESTful Web 服务的大量 HTTP 请求,因此这种额外的流量和延迟是不幸的。
Client
我的期望是,一旦 Jersey 客户端第一次成功通过代理服务器进行身份验证,使用同一实例发出的所有后续请求将自动包含必要的Proxy-Authorization
标头,以防止任何进一步的 407 挑战。根据此链接,这似乎是 HTTP 1.1 的标准方法:
代理服务器在 407(需要代理身份验证)响应中向客户端发送包含质询的 Proxy-Authenticate 标头。客户端然后重复初始请求,但添加一个 Proxy-Authorization 标头,其中包含适合挑战的凭据。成功代理身份验证后,客户端通常会在每个后续请求中向代理发送相同的 Proxy-Authorization 标头,而不是等待再次受到挑战。
所以我的问题是我需要将哪些配置设置应用于 Jersey 客户端或底层 Apache HttpClient 传输层以启用此行为?我已经看到其他各种建议手动添加Proxy-Authorization
标题的帖子,但如果可能的话,我宁愿避免这种解决方法。我还理想地寻找一种可以与我正在使用的所有三种类型的代理身份验证(基本、摘要和 NTLM)一起使用的解决方案。
如果无法阻止所有这些额外的 407 挑战,我还希望在以“可重复”方式从本地文件 POST 或 PUT 数据时提供最佳方法的建议,以防止出现 407 代理身份验证挑战之后的问题。