Authentification de base HttpClient

1. Vue d'ensemble

Ce didacticiel illustrera comment configurer l'authentification de base sur Apache HttpClient 4 .

Si vous souhaitez approfondir et apprendre d'autres choses intéressantes que vous pouvez faire avec HttpClient, rendez-vous au didacticiel principal HttpClient .

2. Authentification de base avec l'API

Commençons par la manière standard de configurer l'authentification de base sur HttpClient - via un 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));

Comme nous pouvons le voir, créer le client avec un fournisseur d'informations d'identification pour le configurer avec l'authentification de base n'est pas difficile.

Maintenant, pour comprendre ce que HttpClient fera réellement dans les coulisses, nous devrons regarder les journaux:

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

L'ensemble de la communication client-serveur est désormais claire :

  • le client envoie la requête HTTP sans informations d'identification
  • le serveur renvoie un défi
  • le client négocie et identifie le bon schéma d'authentification
  • le client envoie une deuxième demande , cette fois avec les informations d'identification

3. Authentification de base préventive

Hors de la boîte, le HttpClient ne fait pas d'authentification préemptive. Au lieu de cela, cela doit être une décision explicite prise par le client.

Tout d'abord, nous devons créer le HttpContext - en le pré- remplissant avec un cache d'authentification avec le bon type de schéma d'authentification présélectionné. Cela signifie que la négociation de l'exemple précédent n'est plus nécessaire - l' authentification de base est déjà choisie :

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

Nous pouvons maintenant utiliser le client avec le nouveau contexte et envoyer la demande de pré-authentification :

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

Regardons les journaux:

[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

Tout semble correct:

  • le schéma «Authentification de base» est présélectionné
  • la demande est envoyée avec l'en- tête d' autorisation
  • le serveur répond avec un 200 OK
  • L'authentification réussit

4. Auth de base avec en-têtes HTTP bruts

L'authentification de base préemptive signifie essentiellement l'envoi préalable de l'en- tête d' autorisation .

Donc, au lieu de passer par l'exemple précédent assez complexe pour le configurer, nous pouvons prendre le contrôle de cet en-tête et le construire à la main :

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

Assurons-nous que cela fonctionne correctement:

[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

Ainsi, même s'il n'y a pas de cache d' authentification , l' authentification de base fonctionne toujours correctement et nous recevons 200 OK.

5. Conclusion

Cet article a illustré différentes façons de configurer et d'utiliser l'authentification de base avec Apache HttpClient 4.

Comme toujours, le code présenté dans cet article est disponible à l'adresse over sur Github. Il s'agit d'un projet basé sur Maven, il devrait donc être facile à importer et à exécuter tel quel.