HttpClient基本認証
1. 概要
このチュートリアルでは、configure Basic Authentication on the Apache HttpClient 4を実行する方法を説明します。
深く掘り下げて、HttpClientでできる他のクールなことを学びたい場合は、the main HttpClient tutorialに進んでください。
参考文献:
HttpAsyncClientチュートリアル
HttpAsyncClientチュートリアル-基本的なGETリクエストを送信し、マルチスレッドクライアントを使用し、SSLとプロキシを使用してクライアントを設定し、最後に認証を行います。
2. APIによる基本認証
the standard way of configuring Basic Authentication on the HttpClient – via a CredentialsProviderから始めましょう:
CredentialsProvider provider = new BasicCredentialsProvider();
UsernamePasswordCredentials credentials
= new UsernamePasswordCredentials("user1", "user1Pass");
provider.setCredentials(AuthScope.ANY, credentials);
HttpClient client = HttpClientBuilder.create()
.setDefaultCredentialsProvider(provider)
.build();
HttpResponse response = client.execute(
new HttpGet(URL_SECURED_BY_BASIC_AUTHENTICATION));
int statusCode = response.getStatusLine()
.getStatusCode();
assertThat(statusCode, equalTo(HttpStatus.SC_OK));
ご覧のとおり、資格情報プロバイダーを使用してクライアントを作成し、基本認証でセットアップすることは難しくありません。
ここで、HttpClientが実際に舞台裏で何をするかを理解するには、ログを確認する必要があります。
# ... request is sent with no credentials
[main] DEBUG ... - Authentication required
[main] DEBUG ... - localhost:8080 requested authentication
[main] DEBUG ... - Authentication schemes in the order of preference:
[negotiate, Kerberos, NTLM, Digest, Basic]
[main] DEBUG ... - Challenge for negotiate authentication scheme not available
[main] DEBUG ... - Challenge for Kerberos authentication scheme not available
[main] DEBUG ... - Challenge for NTLM authentication scheme not available
[main] DEBUG ... - Challenge for Digest authentication scheme not available
[main] DEBUG ... - Selected authentication options: [BASIC]
# ... the request is sent again - with credentials
Client-Server communication is now clear全体:
-
クライアントは資格情報なしでHTTPリクエストを送信します
-
サーバーはチャレンジを送り返します
-
クライアントは正しい認証スキームをネゴシエートおよび識別します
-
クライアントはa second Requestを送信しますが、今回は資格情報を使用します
3. 先制基本認証
箱から出して、HttpClientはプリエンプティブ認証を行いません。 代わりに、これはクライアントが明示的に決定する必要があります。
まず、適切なタイプの認証スキームが事前に選択されたwe need to create the HttpContext – pre-populating it with an authentication cache。 これは、前の例のネゴシエーションが不要になったことを意味します–Basic Authentication is already chosen:
HttpHost targetHost = new HttpHost("localhost", 8082, "http");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials(DEFAULT_USER, DEFAULT_PASS));
AuthCache authCache = new BasicAuthCache();
authCache.put(targetHost, new BasicScheme());
// Add AuthCache to the execution context
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
context.setAuthCache(authCache);
これで、新しいコンテキストとsend the pre-authentication requestでクライアントを使用できます。
HttpClient client = HttpClientBuilder.create().build();
response = client.execute(
new HttpGet(URL_SECURED_BY_BASIC_AUTHENTICATION), context);
int statusCode = response.getStatusLine().getStatusCode();
assertThat(statusCode, equalTo(HttpStatus.SC_OK));
ログを見てみましょう:
[main] DEBUG ... - Re-using cached 'basic' auth scheme for http://localhost:8082
[main] DEBUG ... - Executing request GET /spring-security-rest-basic-auth/api/foos/1 HTTP/1.1
[main] DEBUG ... >> GET /spring-security-rest-basic-auth/api/foos/1 HTTP/1.1
[main] DEBUG ... >> Host: localhost:8082
[main] DEBUG ... >> Authorization: Basic dXNlcjE6dXNlcjFQYXNz
[main] DEBUG ... << HTTP/1.1 200 OK
[main] DEBUG ... - Authentication succeeded
すべてが正常に見えます:
-
「基本認証」スキームが事前に選択されています
-
リクエストはAuthorizationヘッダーで送信されます
-
サーバーは200 OKで応答します
-
認証成功
4. 生のHTTPヘッダーを使用した基本認証
プリエンプティブ基本認証とは、基本的にAuthorizationヘッダーを事前に送信することを意味します。
したがって、前のかなり複雑な例を使用して設定する代わりに、we can take control of this header and construct it by hand:
HttpGet request = new HttpGet(URL_SECURED_BY_BASIC_AUTHENTICATION);
String auth = DEFAULT_USER + ":" + DEFAULT_PASS;
byte[] encodedAuth = Base64.encodeBase64(
auth.getBytes(StandardCharsets.ISO_8859_1));
String authHeader = "Basic " + new String(encodedAuth);
request.setHeader(HttpHeaders.AUTHORIZATION, authHeader);
HttpClient client = HttpClientBuilder.create().build();
HttpResponse response = client.execute(request);
int statusCode = response.getStatusLine().getStatusCode();
assertThat(statusCode, equalTo(HttpStatus.SC_OK));
これが正しく機能していることを確認しましょう。
[main] DEBUG ... - Auth cache not set in the context
[main] DEBUG ... - Opening connection {}->http://localhost:8080
[main] DEBUG ... - Connecting to localhost/127.0.0.1:8080
[main] DEBUG ... - Executing request GET /spring-security-rest-basic-auth/api/foos/1 HTTP/1.1
[main] DEBUG ... - Proxy auth state: UNCHALLENGED
[main] DEBUG ... - http-outgoing-0 >> GET /spring-security-rest-basic-auth/api/foos/1 HTTP/1.1
[main] DEBUG ... - http-outgoing-0 >> Authorization: Basic dXNlcjE6dXNlcjFQYXNz
[main] DEBUG ... - http-outgoing-0 << HTTP/1.1 200 OK
したがって、認証キャッシュがない場合でも、Basic Authentication still works correctly and we receive 200 OK.
5. 結論
この記事では、Apache HttpClient 4で基本認証をセットアップして使用するさまざまな方法を説明しました。
いつものように、この記事で紹介されているコードはover on Githubで利用できます。 これはMavenベースのプロジェクトであるため、インポートしてそのまま実行するのは簡単です。