Skip to content

Commit 166963e

Browse files
committed
Provided option to Preemtive authorization, closes android-async-http#426
1 parent e2d7f0c commit 166963e

File tree

2 files changed

+103
-5
lines changed

2 files changed

+103
-5
lines changed

library/src/main/java/com/loopj/android/http/AsyncHttpClient.java

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,19 @@
2424
import org.apache.http.Header;
2525
import org.apache.http.HeaderElement;
2626
import org.apache.http.HttpEntity;
27+
import org.apache.http.HttpException;
2728
import org.apache.http.HttpHost;
2829
import org.apache.http.HttpRequest;
2930
import org.apache.http.HttpRequestInterceptor;
3031
import org.apache.http.HttpResponse;
3132
import org.apache.http.HttpResponseInterceptor;
3233
import org.apache.http.HttpVersion;
3334
import org.apache.http.auth.AuthScope;
35+
import org.apache.http.auth.AuthState;
36+
import org.apache.http.auth.Credentials;
3437
import org.apache.http.auth.UsernamePasswordCredentials;
3538
import org.apache.http.client.CookieStore;
39+
import org.apache.http.client.CredentialsProvider;
3640
import org.apache.http.client.HttpClient;
3741
import org.apache.http.client.methods.HttpDelete;
3842
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
@@ -50,6 +54,7 @@
5054
import org.apache.http.conn.scheme.SchemeRegistry;
5155
import org.apache.http.conn.ssl.SSLSocketFactory;
5256
import org.apache.http.entity.HttpEntityWrapper;
57+
import org.apache.http.impl.auth.BasicScheme;
5358
import org.apache.http.impl.client.DefaultHttpClient;
5459
import org.apache.http.impl.client.DefaultRedirectHandler;
5560
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
@@ -58,6 +63,7 @@
5863
import org.apache.http.params.HttpParams;
5964
import org.apache.http.params.HttpProtocolParams;
6065
import org.apache.http.protocol.BasicHttpContext;
66+
import org.apache.http.protocol.ExecutionContext;
6167
import org.apache.http.protocol.HttpContext;
6268
import org.apache.http.protocol.SyncBasicHttpContext;
6369

@@ -256,6 +262,24 @@ public void process(HttpResponse response, HttpContext context) {
256262
}
257263
});
258264

265+
httpClient.addRequestInterceptor(new HttpRequestInterceptor() {
266+
public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
267+
AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);
268+
CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(
269+
ClientContext.CREDS_PROVIDER);
270+
HttpHost targetHost = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
271+
272+
if (authState.getAuthScheme() == null) {
273+
AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort());
274+
Credentials creds = credsProvider.getCredentials(authScope);
275+
if (creds != null) {
276+
authState.setAuthScheme(new BasicScheme());
277+
authState.setCredentials(creds);
278+
}
279+
}
280+
}
281+
}, 0);
282+
259283
httpClient.setHttpRequestRetryHandler(new RetryHandler(DEFAULT_MAX_RETRIES, DEFAULT_RETRY_SLEEP_TIME_MILLIS));
260284
}
261285

@@ -414,7 +438,6 @@ public void setProxy(String hostname, int port, String username, String password
414438
httpParams.setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
415439
}
416440

417-
418441
/**
419442
* Sets the SSLSocketFactory to user when making requests. By default, a new, default
420443
* SSLSocketFactory is used.
@@ -462,8 +485,19 @@ public void removeHeader(String header) {
462485
* @param password Basic Auth password
463486
*/
464487
public void setBasicAuth(String username, String password) {
465-
AuthScope scope = AuthScope.ANY;
466-
setBasicAuth(username, password, scope);
488+
setBasicAuth(username, password, false);
489+
}
490+
491+
/**
492+
* Sets basic authentication for the request. Uses AuthScope.ANY. This is the same as
493+
* setBasicAuth('username','password',AuthScope.ANY)
494+
*
495+
* @param username Basic Auth username
496+
* @param password Basic Auth password
497+
* @param preemtive sets authorization in preemtive manner
498+
*/
499+
public void setBasicAuth(String username, String password, boolean preemtive) {
500+
setBasicAuth(username, password, null, preemtive);
467501
}
468502

469503
/**
@@ -475,12 +509,40 @@ public void setBasicAuth(String username, String password) {
475509
* @param scope - an AuthScope object
476510
*/
477511
public void setBasicAuth(String username, String password, AuthScope scope) {
512+
setBasicAuth(username, password, scope, false);
513+
}
514+
515+
/**
516+
* Sets basic authentication for the request. You should pass in your AuthScope for security. It
517+
* should be like this setBasicAuth("username","password", new AuthScope("host",port,AuthScope.ANY_REALM))
518+
*
519+
* @param username Basic Auth username
520+
* @param password Basic Auth password
521+
* @param scope an AuthScope object
522+
* @param preemtive sets authorization in preemtive manner
523+
*/
524+
public void setBasicAuth(String username, String password, AuthScope scope, boolean preemtive) {
478525
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username, password);
479-
this.httpClient.getCredentialsProvider().setCredentials(scope, credentials);
526+
this.httpClient.getCredentialsProvider().setCredentials(scope == null ? AuthScope.ANY : scope, credentials);
527+
setAuthenticationPreemptive(preemtive);
528+
}
529+
530+
/**
531+
* Sets HttpRequestInterceptor which handles authorization in preemtive way, as workaround you
532+
* can use call `AsyncHttpClient.addHeader("Authorization","Basic base64OfUsernameAndPassword==")`
533+
*
534+
* @param isPreemtive whether the authorization is processed in preemtive way
535+
*/
536+
public void setAuthenticationPreemptive(boolean isPreemtive) {
537+
if (isPreemtive) {
538+
httpClient.addRequestInterceptor(new PreemtiveAuthorizationHttpRequestInterceptor(), 0);
539+
} else {
540+
httpClient.removeRequestInterceptorByClass(PreemtiveAuthorizationHttpRequestInterceptor.class);
541+
}
480542
}
481543

482544
/**
483-
* Removes set basic auth credentials
545+
* Removes previously set basic auth credentials
484546
*/
485547
public void clearBasicAuth() {
486548
this.httpClient.getCredentialsProvider().clear();
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.loopj.android.http;
2+
3+
import org.apache.http.HttpException;
4+
import org.apache.http.HttpHost;
5+
import org.apache.http.HttpRequest;
6+
import org.apache.http.HttpRequestInterceptor;
7+
import org.apache.http.auth.AuthScope;
8+
import org.apache.http.auth.AuthState;
9+
import org.apache.http.auth.Credentials;
10+
import org.apache.http.client.CredentialsProvider;
11+
import org.apache.http.client.protocol.ClientContext;
12+
import org.apache.http.impl.auth.BasicScheme;
13+
import org.apache.http.protocol.ExecutionContext;
14+
import org.apache.http.protocol.HttpContext;
15+
16+
import java.io.IOException;
17+
18+
public class PreemtiveAuthorizationHttpRequestInterceptor implements HttpRequestInterceptor {
19+
20+
public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
21+
AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);
22+
CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(
23+
ClientContext.CREDS_PROVIDER);
24+
HttpHost targetHost = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
25+
26+
if (authState.getAuthScheme() == null) {
27+
AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort());
28+
Credentials creds = credsProvider.getCredentials(authScope);
29+
if (creds != null) {
30+
authState.setAuthScheme(new BasicScheme());
31+
authState.setCredentials(creds);
32+
}
33+
}
34+
}
35+
36+
}

0 commit comments

Comments
 (0)