4

HttpClient 4.2.2 とユーザー名/パスワードのプロキシに問題があります。HttpClient は次のように機能します。

  1. リスト項目
  2. プロキシなしでリクエストを送信します(ただし、リクエストごとにプロキシパラメータを設定します)
  3. 407 エラーで Squid からの応答を取得する
  4. プロキシのものでリクエストを送信する

これは非常に奇妙な動作です。各リクエストにプロキシに関する情報を追加することは可能ですか? ハードコーディングされた「Proxy-Authorization」ヘッダーを各リクエストに追加しようとしましたが、正常に動作します。なぜ 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 -

ハードコーディングされたヘッダー付き

Java ログと squid ログに 407 エラーはありません

イカ原木

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 -
4

2 に答える 2

5

HTTP プロキシを使用した認証プロセスは、RFC2616 §14.33および §14.34 で説明されており、HttpClient の場合とまったく同じです。以下が含まれます。

  • 要求されたリソースに適用可能なチャレンジを含むProxy-Authenticateヘッダーを含む407 (Proxy Authentication Required)応答を送信するプロキシ、
  • クライアントは、認証情報を含む資格情報で構成されるProxy-Authorizationヘッダーを使用して新しい要求を発行します。

HttpClient を使用したプリエンプティブ認証の実装については、このチュートリアル(セクション §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);
于 2012-11-28T21:55:34.727 に答える
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 ですか、それともホスト名ですか?

編集

何が起こっているのか理解できたと思います。基本認証を機能させるには、リクエストごとに送信する必要があります。複数回実行する場合は、認証データをキャッシュするメカニズムが必要になります。現在の方法でクライアントを実行することにより、リクエストごとに作成されるため、それを保存できる「コンテキスト」はありません。

注目すべきもう 1 つの項目は、クライアント チュートリアルのセクション 4.7 と 4.8 です。407 エラーとそれに続く BASIC 認証による要求を完全に排除したい場合は、必ずセクション 4.8 を読んでください。

これはクライアントの状態コンテナとして機能するため、彼らが定義した「localcontext」変数に細心の注意を払ってください。

于 2012-11-08T11:36:06.067 に答える