View Javadoc

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 org.apache.http.impl.client;
29  
30  import java.util.Locale;
31  import java.util.Map;
32  import java.util.Queue;
33  
34  import org.apache.commons.logging.Log;
35  import org.apache.commons.logging.LogFactory;
36  import org.apache.http.Header;
37  import org.apache.http.HttpHost;
38  import org.apache.http.HttpResponse;
39  import org.apache.http.auth.AuthProtocolState;
40  import org.apache.http.auth.AuthOption;
41  import org.apache.http.auth.AuthScheme;
42  import org.apache.http.auth.AuthState;
43  import org.apache.http.auth.MalformedChallengeException;
44  import org.apache.http.client.AuthenticationStrategy;
45  import org.apache.http.protocol.HttpContext;
46  
47  public class HttpAuthenticator {
48  
49      private final Log log;
50  
51      public HttpAuthenticator(final Log log) {
52          super();
53          this.log = log != null ? log : LogFactory.getLog(getClass());
54      }
55  
56      public HttpAuthenticator() {
57          this(null);
58      }
59  
60      public boolean isAuthenticationRequested(
61              final HttpHost host,
62              final HttpResponse response,
63              final AuthenticationStrategy authStrategy,
64              final AuthState authState,
65              final HttpContext context) {
66          if (authStrategy.isAuthenticationRequested(host, response, context)) {
67              if (authState.getState() == AuthProtocolState.SUCCESS) {
68                  authStrategy.authFailed(host, authState.getAuthScheme(), context);
69              }
70              this.log.debug("Authentication required");
71              return true;
72          } else {
73              switch (authState.getState()) {
74              case CHALLENGED:
75              case HANDSHAKE:
76                  this.log.debug("Authentication succeeded");
77                  authState.setState(AuthProtocolState.SUCCESS);
78                  authStrategy.authSucceeded(host, authState.getAuthScheme(), context);
79                  break;
80              case SUCCESS:
81                  break;
82              default:
83                  authState.setState(AuthProtocolState.UNCHALLENGED);
84              }
85              return false;
86          }
87      }
88  
89      public boolean authenticate(
90              final HttpHost host,
91              final HttpResponse response,
92              final AuthenticationStrategy authStrategy,
93              final AuthState authState,
94              final HttpContext context) {
95          try {
96              if (this.log.isDebugEnabled()) {
97                  this.log.debug(host.toHostString() + " requested authentication");
98              }
99              Map<String, Header> challenges = authStrategy.getChallenges(host, response, context);
100             if (challenges.isEmpty()) {
101                 this.log.debug("Response contains no authentication challenges");
102                 return false;
103             }
104 
105             AuthScheme authScheme = authState.getAuthScheme();
106             switch (authState.getState()) {
107             case FAILURE:
108                 return false;
109             case SUCCESS:
110                 authState.reset();
111                 break;
112             case CHALLENGED:
113             case HANDSHAKE:
114                 if (authScheme == null) {
115                     this.log.debug("Auth scheme is null");
116                     authStrategy.authFailed(host, null, context);
117                     authState.reset();
118                     authState.setState(AuthProtocolState.FAILURE);
119                     return false;
120                 }
121             case UNCHALLENGED:
122                 if (authScheme != null) {
123                     String id = authScheme.getSchemeName();
124                     Header challenge = challenges.get(id.toLowerCase(Locale.US));
125                     if (challenge != null) {
126                         this.log.debug("Authorization challenge processed");
127                         authScheme.processChallenge(challenge);
128                         if (authScheme.isComplete()) {
129                             this.log.debug("Authentication failed");
130                             authStrategy.authFailed(host, authState.getAuthScheme(), context);
131                             authState.reset();
132                             authState.setState(AuthProtocolState.FAILURE);
133                             return false;
134                         } else {
135                             authState.setState(AuthProtocolState.HANDSHAKE);
136                             return true;
137                         }
138                     } else {
139                         authState.reset();
140                         // Retry authentication with a different scheme
141                     }
142                 }
143             }
144             Queue<AuthOption> authOptions = authStrategy.select(challenges, host, response, context);
145             if (authOptions != null && !authOptions.isEmpty()) {
146                 if (this.log.isDebugEnabled()) {
147                     this.log.debug("Selected authentication options: " + authOptions);
148                 }
149                 authState.setState(AuthProtocolState.CHALLENGED);
150                 authState.update(authOptions);
151                 return true;
152             } else {
153                 return false;
154             }
155         } catch (MalformedChallengeException ex) {
156             if (this.log.isWarnEnabled()) {
157                 this.log.warn("Malformed challenge: " +  ex.getMessage());
158             }
159             authState.reset();
160             return false;
161         }
162     }
163 
164 }