View Javadoc

    1   /* Copyright 2004 Acegi Technology Pty Limited
    2    *
    3    * Licensed under the Apache License, Version 2.0 (the "License");
    4    * you may not use this file except in compliance with the License.
    5    * You may obtain a copy of the License at
    6    *
    7    *     http://www.apache.org/licenses/LICENSE-2.0
    8    *
    9    * Unless required by applicable law or agreed to in writing, software
    10   * distributed under the License is distributed on an "AS IS" BASIS,
    11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12   * See the License for the specific language governing permissions and
    13   * limitations under the License.
    14   */
    15
    16  package org.acegisecurity.adapters.cas;
    17
    18  import edu.yale.its.tp.cas.auth.PasswordHandler;
    19
    20  import org.apache.commons.logging.Log;
    21  import org.apache.commons.logging.LogFactory;
    22
    23  import org.springframework.context.ApplicationContext;
    24
    25  import org.springframework.web.context.support.WebApplicationContextUtils;
    26
    27  import java.util.Map;
    28
    29  import javax.servlet.ServletRequest;
    30  import javax.servlet.http.HttpServletRequest;
    31
    32
    33  /***
    34   * Enables CAS to use the Acegi Security System for authentication.
    35   *
    36   * <P>
    37   * This class works along with {@link CasPasswordHandler} to enable users to
    38   * easily migrate from stand-alone Acegi Security System deployments to
    39   * enterprise-wide CAS deployments.
    40   * </p>
    41   *
    42   * <p>
    43   * It should be noted that the Acegi Security System will operate as a CAS
    44   * client irrespective of the <code>PasswordHandler</code> used on the CAS
    45   * server. In other words, this class need <B>not</B> be used on the CAS
    46   * server if not desired. It exists solely for the convenience of users
    47   * wishing have CAS delegate to an Acegi Security System-based
    48   * <code>AuthenticationManager</code>.
    49   * </p>
    50   *
    51   * <p>
    52   * This class works requires a properly configured
    53   * <code>CasPasswordHandler</code>. On the first authentication request, the
    54   * class will use Spring's {@link
    55   * WebApplicationContextUtils#getWebApplicationContext(ServletContext sc)}
    56   * method to obtain an <code>ApplicationContext</code> instance, inside which
    57   * must be a configured <code>CasPasswordHandler</code> instance. The
    58   * <code>CasPasswordHandlerProxy</code> will then delegate authentication
    59   * requests to that instance.
    60   * </p>
    61   *
    62   * <p>
    63   * To configure CAS to use this class, edit CAS' <code>web.xml</code> and
    64   * define the <code>edu.yale.its.tp.cas.authHandler</code> context parameter
    65   * with the value
    66   * <code>org.acegisecurity.adapters.cas.CasPasswordHandlerProxy</code>.
    67   * </p>
    68   *
    69   * @author Ben Alex
    70   * @version $Id: CasPasswordHandlerProxy.java,v 1.2 2005/11/17 00:56:28 benalex Exp $
    71   */
    72  public class CasPasswordHandlerProxy implements PasswordHandler {
    73      //~ Static fields/initializers =============================================
    74
    75      private static final Log logger = LogFactory.getLog(CasPasswordHandlerProxy.class);
    76
    77      //~ Instance fields ========================================================
    78
    79      private ApplicationContext ctx;
    80      private CasPasswordHandler handler;
    81
    82      //~ Methods ================================================================
    83
    84      /***
    85       * Called by CAS when authentication is required.
    86       *
    87       * <P>
    88       * Delegates to the <code>CasPasswordHandler</code>.
    89       * </p>
    90       *
    91       * @param request as provided by CAS
    92       * @param username provided to CAS
    93       * @param password provided to CAS
    94       *
    95       * @return whether authentication was successful or not
    96       *
    97       * @throws IllegalArgumentException if the application context does not
    98       *         contain a <code>CasPasswordHandler</code> or the
    99       *         <code>ServletRequest</code> was not of type
    100      *         <code>HttpServletRequest</code>
    101      */
    102     public boolean authenticate(ServletRequest request, String username,
    103         String password) {
    104         if (ctx == null) {
    105             if (!(request instanceof HttpServletRequest)) {
    106                 throw new IllegalArgumentException(
    107                     "Can only process HttpServletRequest");
    108             }
    109
    110             HttpServletRequest httpRequest = (HttpServletRequest) request;
    111
    112             ctx = this.getContext(httpRequest);
    113         }
    114
    115         if (handler == null) {
    116             Map beans = ctx.getBeansOfType(CasPasswordHandler.class, true, true);
    117
    118             if (beans.size() == 0) {
    119                 throw new IllegalArgumentException(
    120                     "Bean context must contain at least one bean of type CasPasswordHandler");
    121             }
    122
    123             String beanName = (String) beans.keySet().iterator().next();
    124             handler = (CasPasswordHandler) beans.get(beanName);
    125         }
    126
    127         return handler.authenticate(request, username, password);
    128     }
    129
    130     /***
    131      * Allows test cases to override where application context obtained from.
    132      *
    133      * @param httpRequest which can be used to find the
    134      *        <code>ServletContext</code>
    135      *
    136      * @return the Spring application context
    137      */
    138     protected ApplicationContext getContext(HttpServletRequest httpRequest) {
    139         return WebApplicationContextUtils.getRequiredWebApplicationContext(httpRequest.getSession()
    140                                                                                       .getServletContext());
    141     }
    142 }