2012-11-08 103 views
2

我有一个问题,HttpClient 4.2.2和代理用户名/密码。 HttpClient的这样工作的:HttpClient 4.2.2和代理用户名/密码

  1. 列表项
  2. 无代理的东西
  3. 发送请求(不过我设置为每个请求代理参数)
  4. 从鱿鱼获取响应与407错误
  5. 与代理
  6. 发送查询请求东西

这是非常奇怪的行为,是否有可能为每个请求添加有关代理的信息?我试图为每个请求添加硬编码的“代理授权”头,它工作正常,为什么HttpClient不能做同样的事情?

Java代码

DefaultHttpClient httpClient = new DefaultHttpClient(); 
httpClient.getParams().setParameter(PROTOCOL_VERSION, HTTP_1_1); 
... 
String proxyServer = getProxyServer(); 
int proxyPort = getProxyPort(); 
List<String> authpref = new ArrayList<String>(); 
authpref.add(AuthPolicy.BASIC); 
httpClient.getParams().setParameter(AuthPNames.PROXY_AUTH_PREF, authpref); 
String proxyUser = getProxyUser(); 
String proxyPassword = getProxyPassword(); 
CredentialsProvider credsProvider = httpClient.getCredentialsProvider(); 
credsProvider.setCredentials(new AuthScope(proxyServer, proxyPort), new UsernamePasswordCredentials(proxyUser, proxyPassword)); 
httpClient.setCredentialsProvider(credsProvider); 
HttpHost proxy = new HttpHost(proxyServer, proxyPort, (proxyServer.indexOf("https") != 0) ? "http" : "https"); 
httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); 
... 
HttpPut put = new HttpPut(url); 

/*** hardcoded header ***/ 
//put.addHeader("Proxy-Authorization", "Basic eHRlbmR4LmRuZXByOnF3ZXJ0eQ=="); 
/*** hardcoded header ***/ 

put.setEntity(entity); 
httpClient.execute(put); 
httpClient.getConnectionManager().shutdown(); 


[DefaultClientConnection] Sending request: PUT http://172.26.27.22:8080/myapp/rest/2/3/29/image1.jpg HTTP/1.1 
[headers] >> PUT http://172.26.27.22:8080/myapp/rest/2/3/29/image1.jpg HTTP/1.1 
[headers] >> Authorization: Basic eGRldjo0YTFmNmMwOTgyYWRkMWQ0NDg1YjRhMGE4YWMxY2JjMWNiMTA0ODc1 
[headers] >> Content-Length: 2 
[headers] >> Host: 172.26.27.22:8080 
[headers] >> Proxy-Connection: Keep-Alive 
[headers] >> User-Agent: Apache-HttpClient/4.2.2 (java 1.5) 
[DefaultClientConnection] Receiving response: HTTP/1.0 407 Proxy Authentication Required 
[headers] << HTTP/1.0 407 Proxy Authentication Required 
[headers] << Server: squid/2.7.STABLE8 
[headers] << Date: Thu, 08 Nov 2012 10:09:49 GMT 
[headers] << Content-Type: text/html 
[headers] << Content-Length: 1431 
[headers] << X-Squid-Error: ERR_CACHE_ACCESS_DENIED 0 
[headers] << Proxy-Authenticate: Basic realm="Please, enter username and password" 
[headers] << X-Cache: MISS from 172.26.27.94 
[headers] << X-Cache-Lookup: NONE from 172.26.27.94:3128 
[headers] << Via: 1.0 172.26.27.94:3128 (squid/2.7.STABLE8) 
[headers] << Connection: close 
[DefaultHttpClient] Authentication required 
[DefaultHttpClient] 172.26.27.94:3128 requested authentication 
[ProxyAuthenticationStrategy] Authentication schemes in the order of preference: [Basic] 
[DefaultHttpClient] Selected authentication options: [BASIC] 
[DefaultClientConnection] Connection 0.0.0.0:63344<->172.26.27.94:3128 closed 
[DefaultClientConnectionOperator] Connecting to 172.26.27.94:3128 
[RequestAddCookies] CookieSpec selected: best-match 
[RequestAuthCache] Re-using cached 'basic' auth scheme for http://172.26.27.22:8080 
[RequestAuthCache] No credentials for preemptive authentication 
[RequestProxyAuthentication] Proxy auth state: CHALLENGED 
[RequestProxyAuthentication] Generating response to an authentication challenge using basic scheme 
[DefaultHttpClient] Attempt 2 to execute request 
[DefaultClientConnection] Sending request: PUT http://172.26.27.22:8080/myapp/rest/2/3/29/image1.jpg HTTP/1.1 
[headers] >> PUT http://172.26.27.22:8080/myapp/rest/2/3/29/image1.jpg HTTP/1.1 
[headers] >> Authorization: Basic eGRldjo0YTFmNmMwOTgyYWRkMWQ0NDg1YjRhMGE4YWMxY2JjMWNiMTA0ODc1 
[headers] >> Content-Length: 2 
[headers] >> Host: 172.26.27.22:8080 
[headers] >> Proxy-Connection: Keep-Alive 
[headers] >> User-Agent: Apache-HttpClient/4.2.2 (java 1.5) 
[headers] >> Proxy-Authorization: Basic eHRlbmR4LmRuZXByOnF3ZXJ0eQ== 
[DefaultClientConnection] Receiving response: HTTP/1.0 201 Created 
[headers] << HTTP/1.0 201 Created 
[headers] << Content-Length: 0 
[headers] << Date: Thu, 08 Nov 2012 10:09:49 GMT 
[headers] << X-Cache: MISS from 172.26.27.94 
[headers] << X-Cache-Lookup: MISS from 172.26.27.94:3128 
[headers] << Via: 1.1 172.26.27.94:3128 (squid/2.7.STABLE8) 
[headers] << Connection: keep-alive 
[headers] << Proxy-Connection: keep-alive 

鱿鱼日志

1352370666.778  0 172.26.27.94 TCP_DENIED/407 1870 PUT http://172.26.27.22:8080/myapp/rest/2/3/29/image1.jpg - NONE/- text/html 
1352370671.429  8 172.26.27.94 TCP_MISS/201 282 PUT http://172.26.27.22:8080/myapp/rest/2/3/29/image1.jpg proxyuser DIRECT/172.26.27.22 - 
1352370671.474  0 172.26.27.94 TCP_DENIED/407 1882 PUT http://172.26.27.22:8080/myapp/rest/2/3/29/image2.jpg - NONE/- text/html 
1352370671.486  7 172.26.27.94 TCP_MISS/201 282 PUT http://172.26.27.22:8080/myapp/rest/2/3/29/image2.jpg proxyuser DIRECT/172.26.27.22 - 

随着硬编码标题

没有407错误在java日志和鱿鱼日志

鱿鱼日志

1352370542.016  8 172.26.27.94 TCP_MISS/201 282 PUT http://172.26.27.22:8080/myapp/rest/2/3/29/image1.jpg proxyuser DIRECT/172.26.27.22 - 
1352370542.033  7 172.26.27.94 TCP_MISS/201 282 PUT http://172.26.27.22:8080/myapp/rest/2/3/29/image2.jpg proxyuser DIRECT/172.26.27.22 - 

回答

0

这是你的AuthScope:

// You set proxyServer here vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv 
credsProvider.setCredentials(new AuthScope(proxyServer, proxyPort), new UsernamePasswordCredentials(proxyUser, proxyPassword)); 
httpClient.setCredentialsProvider(credsProvider); 
// But here you are looking for the indexof https to determine if it is an SSL proxy 
// is the String returned from getProxyServer() above a URL or a host name? 
HttpHost proxy = new HttpHost(proxyServer, proxyPort, (proxyServer.indexOf("https") != 0) ? "http" : "https"); 
httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); 

埋在我的上述评论 - 是串由getProxyServer()URL或主机名返回?

编辑

我想我已经想通了,这是怎么回事。每次请求都必须发送基本身份验证才能正常工作。如果您正在进行多次执行,您将需要一些机制来缓存身份验证数据。通过以现在的方式执行客户端,没有可以存储的“上下文”,因为每个请求都会创建一个“上下文”。

另一个要看的项目是client tutorial第4.7和4.8节。如果您希望完全消除407错误,然后使用BASIC身份验证请求,请确保您阅读第4.8节。

对他们定义的“localcontext”变量非常关注,因为它充当客户端的状态容器。

+0

getProxyServer()返回的IP地址 – Lazy

+0

有趣......有你尝试了没有http/https检查的HttpHost?我想知道这是否会产生任何影响 - 除此之外,我会尝试使用调试器来追查它是否尝试使用已配置的代理。 –

+0

是的,我试过没有http/https,结果是一样的。 – Lazy

5

在RFC2616 §14.33和§14.34中描述了使用HTTP代理的身份验证过程,与您在HttpClient中看到的过程完全相同。它包括:

  • 代理发送407(代理身份验证)与含有适用于所请求的资源的挑战代理身份验证响应,
  • 客户端发出与一个新的请求代理授权头部由包含认证信息的凭证组成。

实现带有HttpClient的抢占式认证在this tutorial(部分§4.8)被描述,并且需要预先填充客户对象的认证缓存。 不幸的是,当对代理服务器进行预验证时,它们的代码不起作用。它可能是一个有点棘手,以了解如何得到它的权利,但实际上它是作为传递参数给BasicScheme构造简单:

AuthCache authCache = new BasicAuthCache(); 

AuthScheme basicAuthScheme = null; 
if (isProxy) { 
    basicAuthScheme = new BasicScheme(ChallengeState.PROXY); 
} else { 
    basicAuthScheme = new BasicScheme(ChallengeState.TARGET); 
} 

authCache.put(host, basicAuthScheme); 
httpContext.setAttribute(ClientContext.AUTH_CACHE, authCache); 
相关问题