View Javadoc

1   /*
2    * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/auth/AuthChallengeProcessor.java,v 1.2 2004/04/18 23:51:36 jsdever Exp $
3    * $Revision: 290260 $
4    * $Date: 2005-09-19 16:37:48 -0400 (Mon, 19 Sep 2005) $
5    *
6    * ====================================================================
7    *
8    *  Copyright 2002-2004 The Apache Software Foundation
9    *
10   *  Licensed under the Apache License, Version 2.0 (the "License");
11   *  you may not use this file except in compliance with the License.
12   *  You may obtain a copy of the License at
13   *
14   *      http://www.apache.org/licenses/LICENSE-2.0
15   *
16   *  Unless required by applicable law or agreed to in writing, software
17   *  distributed under the License is distributed on an "AS IS" BASIS,
18   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19   *  See the License for the specific language governing permissions and
20   *  limitations under the License.
21   * ====================================================================
22   *
23   * This software consists of voluntary contributions made by many
24   * individuals on behalf of the Apache Software Foundation.  For more
25   * information on the Apache Software Foundation, please see
26   * <http://www.apache.org/>.
27   *
28   */
29  
30  package org.apache.commons.httpclient.auth;
31  
32  import java.util.Collection;
33  import java.util.Iterator;
34  import java.util.Map;
35  
36  import org.apache.commons.httpclient.params.HttpParams;
37  import org.apache.commons.logging.Log;
38  import org.apache.commons.logging.LogFactory;
39  
40  /***
41   * This class provides utility methods for processing HTTP www and proxy authentication 
42   * challenges.
43   * 
44   * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
45   * 
46   * @since 3.0
47   */
48  public final class AuthChallengeProcessor {
49  
50      private static final Log LOG = LogFactory.getLog(AuthChallengeProcessor.class);
51  
52      private HttpParams params = null;
53      
54      /***
55       * Creates an authentication challenge processor with the given {@link HttpParams HTTP 
56       * parameters}
57       * 
58       * @param params the {@link HttpParams HTTP parameters} used by this processor
59       */
60      public AuthChallengeProcessor(final HttpParams params) {
61          super();
62          if (params == null) {
63              throw new IllegalArgumentException("Parameter collection may not be null");
64          }
65          this.params = params;
66      }
67  
68      /***
69       * Determines the preferred {@link AuthScheme authentication scheme} that can be used 
70       * to respond to the given collection of challenges.
71       * 
72       * @param challenges the collection of authentication challenges
73       * 
74       * @return the preferred {@link AuthScheme authentication scheme}
75       * 
76       * @throws AuthChallengeException if the preferred authentication scheme 
77       * cannot be determined or is not supported
78       */
79      public AuthScheme selectAuthScheme(final Map challenges) throws AuthChallengeException {
80          if (challenges == null) {
81              throw new IllegalArgumentException("Challenge map may not be null"); 
82          }
83          Collection authPrefs = (Collection) this.params.getParameter(
84              AuthPolicy.AUTH_SCHEME_PRIORITY);
85          if (authPrefs == null || authPrefs.isEmpty()) {
86              authPrefs = AuthPolicy.getDefaultAuthPrefs();    
87          }
88          if (LOG.isDebugEnabled()) {
89              LOG.debug("Supported authentication schemes in the order of preference: " 
90                  + authPrefs);
91          }
92          AuthScheme authscheme = null;
93          String challenge = null;
94          Iterator item = authPrefs.iterator();
95          while (item.hasNext()) {
96              String id = (String) item.next();
97              challenge = (String) challenges.get(id.toLowerCase()); 
98              if (challenge != null) {
99                  if (LOG.isInfoEnabled()) {
100                     LOG.info(id + " authentication scheme selected");
101                 }
102                 try {
103                     authscheme = AuthPolicy.getAuthScheme(id);
104                 } catch (IllegalStateException e) {
105                     throw new AuthChallengeException(e.getMessage());
106                 }
107                 break;
108             } else {
109                 if (LOG.isDebugEnabled()) {
110                     LOG.debug("Challenge for " + id + " authentication scheme not available");
111                     // Try again
112                 }
113             }
114         }
115         if (authscheme == null) {
116             // If none selected, something is wrong
117             throw new AuthChallengeException(
118                 "Unable to respond to any of these challenges: "
119                     + challenges);
120         }
121         return authscheme;
122     }
123 
124     /***
125      * Processes the given collection of challenges and updates the 
126      * {@link AuthState state} of the authentication process.
127      * 
128      * @param challenges the collection of authentication challenges
129      * 
130      * @return the {@link AuthScheme authentication scheme} used to 
131      * process the challenge
132      * 
133      * @throws AuthChallengeException if authentication challenges cannot be 
134      * successfully processed or the preferred authentication scheme cannot
135      * be determined
136      */
137     public AuthScheme processChallenge(final AuthState state, final Map challenges)
138         throws MalformedChallengeException, AuthenticationException
139     {    
140         if (state == null) {
141             throw new IllegalArgumentException("Authentication state may not be null"); 
142         }
143         if (challenges == null) {
144             throw new IllegalArgumentException("Challenge map may not be null"); 
145         }
146         
147         if (state.isPreemptive() || state.getAuthScheme() == null) {
148             // Authentication not attempted before
149             state.setAuthScheme(selectAuthScheme(challenges));
150         }
151         AuthScheme authscheme = state.getAuthScheme();
152         String id = authscheme.getSchemeName();
153         if (LOG.isDebugEnabled()) {
154             LOG.debug("Using authentication scheme: " + id);
155         }
156         String challenge = (String) challenges.get(id.toLowerCase());
157         if (challenge == null) {
158             throw new AuthenticationException(id + 
159                 " authorization challenge expected, but not found");
160         }
161         authscheme.processChallenge(challenge);
162         LOG.debug("Authorization challenge processed");
163         return authscheme;
164     }
165 }