2012-03-02 14 views
12

私は、HTTPClientバージョン4.1.2を使用して、基本認証を必要とするREST over HTTP APIにアクセスしようとしています。ここでは、クライアントコードは次のとおりです。Basic認証を使用する場合、HTTPClientは2つの要求を送信しますか?

DefaultHttpClient httpClient = new DefaultHttpClient(new ThreadSafeClientConnManager()); 
// Enable HTTP Basic Auth 
httpClient.getCredentialsProvider().setCredentials(
    new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT), 
    new UsernamePasswordCredentials(this.username, this.password)); 

HttpHost proxy = new HttpHost(this.proxyURI.getHost(), this.proxyURI.getPort()); 

httpClient.getParams().setParameter(ConnRouteParams.DEFAULT_PROXY, proxy); 

私はPOSTリクエストを作成すると、次のように:

HttpPost request = new HttpPost("http://my/url"); 
request.addHeader(new BasicHeader("Content-type", "application/atom+xml; type=entry")); // required by vendor 
request.setEntity(new StringEntity("My content")); 

HttpResponse response = client.execute(request); 

私が送信されている2つの要求があることCharles Proxyで参照してください。 1つはAuthorization: Basic ...ヘッダーなしで1つはです。最初のものは401で失敗しますが、2番目のものは201でうまくいっています。

これはなぜ起こるのですか?ありがとう!

EDIT:

私はすでにthis questionを見ていることを明確にする必要がありますが、あなたが見ることができるように私はAuthScope同じように設定し、それは私の問題を解決していませんでした。また、新しいHttpClientを作成しています(ただし、同じConnectionManagerを使用していますが)複数の要求に対して同じHttpClientを使用しても問題は解決しません。

EDIT 2:

何@LastCoderが示唆されたことは実行する方法であるようなので、それが見えます。別の質問にはthis answerを参照してください。この問題は、HTTP仕様に関する知識が不足していることに起因しています。私がやってみたいのは、 "プリエンプティブ認証"と呼ばれ、HttpClientdocs mention it hereです。ありがたいことに、上にリンクされた答えはそれを行うためにはるかに短くてきれいな方法です。

+1

私は、資格情報が指定されていても、同じことが起こっていることに気がつきました。 – Harindaka

+0

これは本当に正常な動作かどうか疑問に思います。クライアントは、認証を前提としないHTTP要求を行い、基本認証が必要であることを(401を介して)伝えられます。理論的には、基本認証は先取りできますが、他の認証方式(例:ダイジェスト)では追加のネゴシエーションが必要です – seand

+0

@seandあなたは私が実際にそれを考慮したことを知っていますが、HTTPプロトコルなどに組み込まれているかどうかはわかりません。 – daveslab

答えて

10

むしろあなただけUSERNAMEコードしない理由)(.setCredentialsを使用するよりも:PASSWORDをして

+0

私はそれを確かに行うことができました。違いがあるかどうかをテストしますが、 'HttpClient'リポジトリのサンプルコード(http://bit.ly/wEsEhY)に従って、これを行うべきですそれ。 – daveslab

+7

@daveslab - リソースを匿名で要求し、Authorizationヘッダーで401に応答するのは、httpクライアント仕様の一部です。それがクライアントではない場合は、Webサーバに必要なものではないAuthorizationヘッダ資格情報を持つWebサーバをスパムします。基本的なセキュリティのベストプラクティスです。 –

+0

これは大胆な解決策ですが、必要に応じてプロトコルを切り替えるのが難しくなります(たとえば、ダイジェスト認証を使用するようにサーバーを変更した場合) – seand

2

これは、サーバー/ターゲット・エンドポイントは、すべてのための新しいセッションを作成していることを意味.addHeader()と認証ヘッダーを追加クライアント要求。これにより、あなたのすべての要求がハンドシェイクを通過するように強制されます。これは、クライアントが最初に電話をかけ、認証が必要であることを認識した後、承認を受けます。あなたがする必要があるのは、次のように事前に承認を送信することです:

httpClient.getParams()。setAuthenticationPreemptive(true);

このプロセスを理解するだけで、クライアントのリクエストヘッダーを記録して、クライアントが送受信しているものを知ることができます。 これが動作するかどうかを確認してください。

関連する問題