53 votes

Authentification de base préemptive avec Apache HttpClient 4

Existe-t-il un moyen plus simple de configurer le client HTTP pour l’authentification de base préventive que ce qui est décrit ici ?
Dans la version précédente (3.x), il s'agissait d'un simple appel de méthode (par exemple, httpClient.getParams().setAuthenticationPreemptive(true) ).
La principale chose que je veux éviter consiste à ajouter BasicHttpContext à chaque méthode que j'exécute.

89voto

Adam Batkin Points 20920

Si vous souhaitez forcer HttpClient 4 à s'authentifier avec une seule requête, les opérations suivantes fonctionneront:

 String username = ...
String password = ...
UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, password);

HttpRequest request = ...
request.addHeader(new BasicScheme().authenticate(creds, request));
 

23voto

Mat Mannion Points 2072

Il est difficile de le faire sans passer à chaque fois dans un contexte, mais vous pouvez probablement le faire en utilisant un intercepteur de requêtes. Voici quelques codes que nous utilisons (trouvés dans leur JIRA, iirc):

 // Pre-emptive authentication to speed things up
BasicHttpContext localContext = new BasicHttpContext();

BasicScheme basicAuth = new BasicScheme();
localContext.setAttribute("preemptive-auth", basicAuth);

httpClient.addRequestInterceptor(new PreemptiveAuthInterceptor(), 0);

(...)

static class PreemptiveAuthInterceptor implements HttpRequestInterceptor {

    public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
        AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);

        // If no auth scheme avaialble yet, try to initialize it
        // preemptively
        if (authState.getAuthScheme() == null) {
            AuthScheme authScheme = (AuthScheme) context.getAttribute("preemptive-auth");
            CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(ClientContext.CREDS_PROVIDER);
            HttpHost targetHost = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
            if (authScheme != null) {
                Credentials creds = credsProvider.getCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()));
                if (creds == null) {
                    throw new HttpException("No credentials for preemptive authentication");
                }
                authState.setAuthScheme(authScheme);
                authState.setCredentials(creds);
            }
        }

    }

}
 

18voto

Oliv Points 828

C'est la même solution que Mat Mannion, mais vous n'avez pas à mettre localContext à chaque demande. C'est plus simple, mais il ajoute authentification à TOUTES les demandes. Utile, si vous n'avez pas de contrôle sur les demandes individuelles, comme dans mon cas lors de l'utilisation d'Apache Solr, qui utilise HttpClient en interne.

httpClient.addRequestInterceptor(new PreemptiveAuthInterceptor(), 0);

(...)

static class PreemptiveAuthInterceptor implements HttpRequestInterceptor {

    public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
        AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);

        // If no auth scheme avaialble yet, try to initialize it
        // preemptively
        if (authState.getAuthScheme() == null) {
            CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(ClientContext.CREDS_PROVIDER);
            HttpHost targetHost = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
            Credentials creds = credsProvider.getCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()));
            if (creds == null)
                throw new HttpException("No credentials for preemptive authentication");
            authState.setAuthScheme(new BasicScheme());
            authState.setCredentials(creds);
        }

    }

}

Bien sûr, vous devez définir les informations d'identification fournisseur de:

httpClient.getCredentialsProvider().setCredentials(
                new AuthScope(url.getHost(), url.getPort()),
                new UsernamePasswordCredentials(username, password))

L' AuthScope ne doit pas contenir de domaine, car il n'est pas connu à l'avance.

6voto

Jonathan Points 545

Un peu tard pour le parti mais je suis tombé sur le fil en essayant de résoudre ceci pour la pré-autorisation par procuration d'une demande de publication. Pour ajouter à la réponse d'Adam, j'ai trouvé ce qui suit fonctionnait pour moi:

 HttpPost httppost = new HttpPost(url);
UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, password);
Header bs = new BasicScheme().authenticate(creds, httppost);
httppost.addHeader("Proxy-Authorization", bs.getValue());
 

Pensée qui pourrait être utile pour quelqu'un d'autre qui se heurte à cela.

6voto

Martin Konecny Points 7328

Je pense que le meilleur moyen peut être de le faire manuellement. J'ai ajouté la fonction suivante

Java classique:

 import javax.xml.bind.DatatypeConverter;
 

...

 private static void addAuthHeader(HttpRequestBase http, String username, String password) throws UnsupportedEncodingException {
        String encoded = DatatypeConverter.printBase64Binary((username + ":" + password).getBytes("UTF-8"));
        http.addHeader("AUTHORIZATION", "Basic " + encoded);
    }
 

HTTPRequestBase peut être une instance de HttpGet ou HttpPost

Android:

 import android.util.Base64;
 

...

 private static void addAuthHeader(HttpRequestBase http, String username, String password) throws UnsupportedEncodingException {
    String encoded = Base64.encodeToString((username + ":" + password).getBytes("UTF-8"), Base64.NO_WRAP);
    http.addHeader("AUTHORIZATION", "Basic " + encoded);
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X