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