首页 文章

重用授权标头以防止Jersey客户端出现多个407代理身份验证问题

提问于
浏览
2

我使用Jersey Client 2.0库(使用Apache HttpClient v4.2.5传输连接器)来使用RESTful Web服务 . 我的应用程序必须支持通过代理服务器与任何Basic,Digest或NTLM身份验证的连接 . 我已经添加了对所有这些类型的代理身份验证的支持,基本上一切都正常 .

这就是我添加对Basic和Digest代理身份验证的支持:

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认证质询响应 . 这是一个问题,原因有两个:

  • 如果我使用 InputStream 提供的实体主体发出 POSTPUT 请求(已经在上一个请求中使用代理服务器成功通过身份验证),则认为是"non-repeatable"请求,因此当收到407质询时,我得到了以下例外:
org.apache.http.client.NonRepeatableRequestException: Cannot retry request with a non-repeatable request entity.

我可以通过将实体主体数据从 InputStream 缓冲到字符串或字节数组来解决此问题,以便在收到407质询时请求是可重复的,但这样做效率低,并且不能解决问题2 .

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

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

代理服务器在407(需要代理身份验证)响应中向客户端发送包含质询的Proxy-Authenticate头 . 然后,客户端重复初始请求,但添加了一个代理授权标头,其中包含适用于质询的凭据 . 成功进行代理身份验证后,客户端通常会在每次后续请求时向代理发送相同的代理授权标头,而不是等待再次提出质询 .

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

如果无法阻止所有这些额外的407挑战,我还希望在以“可重复”方式从本地文件发布或PUTing数据时采用最佳方法的建议,以防止407代理身份验证挑战后出现问题 .

1 回答

  • 3

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

    通过在 ClientConfig 对象上设置以下属性,可以在Jersey Client v2.5中启用请求缓冲,该对象将请求实体处理模式从"chunked"(默认值)更改为"buffered":

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

    现在,我正在使用我必须支持的所有三种代理身份验证:Basic,Digest和NTLM . 我只在用户配置代理服务器时才启用此“缓冲”模式,因为我认为除非绝对必要,否则最好坚持使用默认的“分块”模式 . 我担心在内存中缓冲大量PUT / POST请求的开销,以及在不对数据进行分块时潜在的效率损失 .

    所以现在我的客户端应用程序工作正常,但我仍然非常有兴趣听到问题2的任何可能的解决方案,因为最好只触发一个初始的407代理身份验证挑战 Client 实例 . 我怀疑这个问题的任何潜在解决方案都只适用于基本身份验证,因为Digest和NTLM身份验证固有的额外复杂性 .

相关问题