HttpClient Basic Authentication

1. Übersicht

Dieses Tutorial zeigt, wie Sie die Standardauthentifizierung auf dem Apache HttpClient 4 konfigurieren .

Wenn Sie tiefer graben und andere coole Dinge lernen möchten, die Sie mit dem HttpClient tun können, gehen Sie zum Haupt-HttpClient-Tutorial .

2. Grundlegende Authentifizierung mit der API

Beginnen wir mit der Standardmethode zum Konfigurieren der Standardauthentifizierung auf dem HttpClient - über einen 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));

Wie wir sehen können, ist es nicht schwierig, den Client mit einem Anbieter von Anmeldeinformationen zu erstellen, um ihn mit der Standardauthentifizierung einzurichten.

Um zu verstehen, was HttpClient tatsächlich hinter den Kulissen tut, müssen wir uns die Protokolle ansehen:

# ... 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

Die gesamte Client-Server-Kommunikation ist jetzt klar :

  • Der Client sendet die HTTP-Anforderung ohne Anmeldeinformationen
  • Der Server sendet eine Herausforderung zurück
  • Der Client verhandelt und identifiziert das richtige Authentifizierungsschema
  • Der Client sendet eine zweite Anfrage , diesmal mit Anmeldeinformationen

3. Präventive Basisauthentifizierung

Standardmäßig führt der HttpClient keine präemptive Authentifizierung durch. Stattdessen muss dies eine explizite Entscheidung des Kunden sein.

Zuerst müssen wir den HttpContext erstellen und ihn mit einem Authentifizierungscache mit dem richtigen Typ des vorgewählten Authentifizierungsschemas füllen . Dies bedeutet, dass die Aushandlung aus dem vorherigen Beispiel nicht mehr erforderlich ist. Die Standardauthentifizierung ist bereits ausgewählt :

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);

Jetzt können wir den Client mit dem neuen Kontext verwenden und die Vorauthentifizierungsanforderung senden :

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));

Schauen wir uns die Protokolle an:

[main] DEBUG ... - Re-using cached 'basic' auth scheme for //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

Alles sieht in Ordnung aus:

  • Das Schema „Basisauthentifizierung“ ist vorausgewählt
  • Die Anforderung wird mit dem gesendeten Authorization - Header
  • Der Server antwortet mit 200 OK
  • Die Authentifizierung ist erfolgreich

4. Grundlegende Authentifizierung mit unformatierten HTTP-Headern

Präventive Basisauthentifizierung bedeutet im Wesentlichen, den Autorisierungsheader vorab zu senden .

Anstatt das recht komplexe vorherige Beispiel durchzugehen, um es einzurichten, können wir die Kontrolle über diesen Header übernehmen und ihn von Hand erstellen :

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));

Stellen wir sicher, dass dies richtig funktioniert:

[main] DEBUG ... - Auth cache not set in the context [main] DEBUG ... - Opening connection {}->//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

Obwohl kein Authentifizierungscache vorhanden ist, funktioniert die Standardauthentifizierung weiterhin ordnungsgemäß und wir erhalten 200 OK.

5. Schlussfolgerung

In diesem Artikel wurden verschiedene Möglichkeiten zum Einrichten und Verwenden der Basisauthentifizierung mit dem Apache HttpClient 4 erläutert.

Wie immer ist der in diesem Artikel vorgestellte Code auf Github verfügbar. Dies ist ein Maven-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein.