1 /* 2 * ==================================================================== 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * ==================================================================== 20 * 21 * This software consists of voluntary contributions made by many 22 * individuals on behalf of the Apache Software Foundation. For more 23 * information on the Apache Software Foundation, please see 24 * <http://www.apache.org/>. 25 * 26 */ 27 28 package ch.boye.httpclientandroidlib.client.protocol; 29 30 import java.io.IOException; 31 32 import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog; 33 /* LogFactory removed by HttpClient for Android script. */ 34 import ch.boye.httpclientandroidlib.HttpException; 35 import ch.boye.httpclientandroidlib.HttpHost; 36 import ch.boye.httpclientandroidlib.HttpRequest; 37 import ch.boye.httpclientandroidlib.HttpRequestInterceptor; 38 import ch.boye.httpclientandroidlib.annotation.Immutable; 39 import ch.boye.httpclientandroidlib.auth.AuthProtocolState; 40 import ch.boye.httpclientandroidlib.auth.AuthScheme; 41 import ch.boye.httpclientandroidlib.auth.AuthScope; 42 import ch.boye.httpclientandroidlib.auth.AuthState; 43 import ch.boye.httpclientandroidlib.auth.Credentials; 44 import ch.boye.httpclientandroidlib.client.AuthCache; 45 import ch.boye.httpclientandroidlib.client.CredentialsProvider; 46 import ch.boye.httpclientandroidlib.conn.routing.RouteInfo; 47 import ch.boye.httpclientandroidlib.protocol.HttpContext; 48 import ch.boye.httpclientandroidlib.util.Args; 49 50 /** 51 * Request interceptor that can preemptively authenticate against known hosts, 52 * if there is a cached {@link AuthScheme} instance in the local 53 * {@link AuthCache} associated with the given target or proxy host. 54 * 55 * @since 4.1 56 */ 57 @Immutable 58 public class RequestAuthCache implements HttpRequestInterceptor { 59 60 public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass()); 61 RequestAuthCache()62 public RequestAuthCache() { 63 super(); 64 } 65 process(final HttpRequest request, final HttpContext context)66 public void process(final HttpRequest request, final HttpContext context) 67 throws HttpException, IOException { 68 Args.notNull(request, "HTTP request"); 69 Args.notNull(context, "HTTP context"); 70 71 final HttpClientContext clientContext = HttpClientContext.adapt(context); 72 73 final AuthCache authCache = clientContext.getAuthCache(); 74 if (authCache == null) { 75 this.log.debug("Auth cache not set in the context"); 76 return; 77 } 78 79 final CredentialsProvider credsProvider = clientContext.getCredentialsProvider(); 80 if (credsProvider == null) { 81 this.log.debug("Credentials provider not set in the context"); 82 return; 83 } 84 85 final RouteInfo route = clientContext.getHttpRoute(); 86 if (route == null) { 87 this.log.debug("Route info not set in the context"); 88 return; 89 } 90 91 HttpHost target = clientContext.getTargetHost(); 92 if (target == null) { 93 this.log.debug("Target host not set in the context"); 94 return; 95 } 96 97 if (target.getPort() < 0) { 98 target = new HttpHost( 99 target.getHostName(), 100 route.getTargetHost().getPort(), 101 target.getSchemeName()); 102 } 103 104 final AuthState targetState = clientContext.getTargetAuthState(); 105 if (targetState != null && targetState.getState() == AuthProtocolState.UNCHALLENGED) { 106 final AuthScheme authScheme = authCache.get(target); 107 if (authScheme != null) { 108 doPreemptiveAuth(target, authScheme, targetState, credsProvider); 109 } 110 } 111 112 final HttpHost proxy = route.getProxyHost(); 113 final AuthState proxyState = clientContext.getProxyAuthState(); 114 if (proxy != null && proxyState != null && proxyState.getState() == AuthProtocolState.UNCHALLENGED) { 115 final AuthScheme authScheme = authCache.get(proxy); 116 if (authScheme != null) { 117 doPreemptiveAuth(proxy, authScheme, proxyState, credsProvider); 118 } 119 } 120 } 121 doPreemptiveAuth( final HttpHost host, final AuthScheme authScheme, final AuthState authState, final CredentialsProvider credsProvider)122 private void doPreemptiveAuth( 123 final HttpHost host, 124 final AuthScheme authScheme, 125 final AuthState authState, 126 final CredentialsProvider credsProvider) { 127 final String schemeName = authScheme.getSchemeName(); 128 if (this.log.isDebugEnabled()) { 129 this.log.debug("Re-using cached '" + schemeName + "' auth scheme for " + host); 130 } 131 132 final AuthScope authScope = new AuthScope(host, AuthScope.ANY_REALM, schemeName); 133 final Credentials creds = credsProvider.getCredentials(authScope); 134 135 if (creds != null) { 136 if ("BASIC".equalsIgnoreCase(authScheme.getSchemeName())) { 137 authState.setState(AuthProtocolState.CHALLENGED); 138 } else { 139 authState.setState(AuthProtocolState.SUCCESS); 140 } 141 authState.update(authScheme, creds); 142 } else { 143 this.log.debug("No credentials for preemptive authentication"); 144 } 145 } 146 147 } 148