View Javadoc

    1   /* Copyright 2004, 2005 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.catalina;
    17
    18  import org.acegisecurity.Authentication;
    19  import org.acegisecurity.AuthenticationException;
    20  import org.acegisecurity.AuthenticationManager;
    21
    22  import org.acegisecurity.adapters.PrincipalAcegiUserToken;
    23
    24  import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
    25
    26  import org.apache.catalina.Container;
    27  import org.apache.catalina.LifecycleException;
    28  import org.apache.catalina.realm.RealmBase;
    29
    30  import org.apache.commons.logging.Log;
    31  import org.apache.commons.logging.LogFactory;
    32
    33  import org.springframework.context.support.FileSystemXmlApplicationContext;
    34
    35  import java.io.File;
    36
    37  import java.security.Principal;
    38  import java.security.cert.X509Certificate;
    39
    40  import java.util.Map;
    41
    42
    43  /***
    44   * Adapter to enable Catalina (Tomcat) to authenticate via the Acegi Security
    45   * System for Spring.
    46   *
    47   * <p>
    48   * Returns a {@link PrincipalAcegiUserToken} to Catalina's authentication
    49   * system, which is subsequently available via
    50   * <code>HttpServletRequest.getUserPrincipal()</code>.
    51   * </p>
    52   *
    53   * @author Ben Alex
    54   * @version $Id: CatalinaAcegiUserRealm.java,v 1.9 2005/11/25 00:26:30 benalex Exp $
    55   */
    56  public class CatalinaAcegiUserRealm extends RealmBase {
    57      //~ Static fields/initializers =============================================
    58
    59      private static final Log logger = LogFactory.getLog(CatalinaAcegiUserRealm.class);
    60
    61      //~ Instance fields ========================================================
    62
    63      protected final String name = "CatalinaSpringUserRealm / $Id: CatalinaAcegiUserRealm.java,v 1.9 2005/11/25 00:26:30 benalex Exp $";
    64      private AuthenticationManager authenticationManager;
    65      private Container container;
    66      private String appContextLocation;
    67      private String key;
    68
    69      //~ Methods ================================================================
    70
    71      public void setAppContextLocation(String appContextLocation) {
    72          this.appContextLocation = appContextLocation;
    73      }
    74
    75      public String getAppContextLocation() {
    76          return appContextLocation;
    77      }
    78
    79      public void setKey(String key) {
    80          this.key = key;
    81      }
    82
    83      public String getKey() {
    84          return key;
    85      }
    86
    87      public Principal authenticate(String username, String credentials) {
    88          if (username == null) {
    89              return null;
    90          }
    91
    92          if (credentials == null) {
    93              credentials = "";
    94          }
    95
    96          Authentication request = new UsernamePasswordAuthenticationToken(username,
    97                  credentials);
    98          Authentication response = null;
    99
    100         try {
    101             response = authenticationManager.authenticate(request);
    102         } catch (AuthenticationException failed) {
    103             if (logger.isDebugEnabled()) {
    104                 logger.debug("Authentication request for user: " + username
    105                     + " failed: " + failed.toString());
    106             }
    107
    108             return null;
    109         }
    110
    111         return new PrincipalAcegiUserToken(this.key,
    112             response.getPrincipal().toString(),
    113             response.getCredentials().toString(), response.getAuthorities(),
    114             response.getPrincipal());
    115     }
    116
    117     public Principal authenticate(String username, byte[] credentials) {
    118         return authenticate(username, new String(credentials));
    119     }
    120
    121     /***
    122      * Not supported, returns null
    123      *
    124      * @param username DOCUMENT ME!
    125      * @param digest DOCUMENT ME!
    126      * @param nonce DOCUMENT ME!
    127      * @param nc DOCUMENT ME!
    128      * @param cnonce DOCUMENT ME!
    129      * @param qop DOCUMENT ME!
    130      * @param realm DOCUMENT ME!
    131      * @param md5a2 DOCUMENT ME!
    132      *
    133      * @return DOCUMENT ME!
    134      */
    135     public java.security.Principal authenticate(java.lang.String username,
    136         java.lang.String digest, java.lang.String nonce, java.lang.String nc,
    137         java.lang.String cnonce, java.lang.String qop, java.lang.String realm,
    138         java.lang.String md5a2) {
    139         return null;
    140     }
    141
    142     /***
    143      * Not supported, returns null
    144      *
    145      * @param x509Certificates DOCUMENT ME!
    146      *
    147      * @return DOCUMENT ME!
    148      */
    149     public Principal authenticate(X509Certificate[] x509Certificates) {
    150         return null;
    151     }
    152
    153     public boolean hasRole(Principal principal, String role) {
    154         if ((principal == null) || (role == null)) {
    155             return false;
    156         }
    157
    158         if (!(principal instanceof PrincipalAcegiUserToken)) {
    159             logger.warn(
    160                 "Expected passed principal to be of type PrincipalAcegiUserToken but was "
    161                 + principal.getClass().getName());
    162
    163             return false;
    164         }
    165
    166         PrincipalAcegiUserToken test = (PrincipalAcegiUserToken) principal;
    167
    168         return test.isUserInRole(role);
    169     }
    170
    171     /***
    172      * Provides the method that Catalina will use to start the container.
    173      *
    174      * @throws LifecycleException if a problem is detected
    175      */
    176     public void start() throws LifecycleException {
    177         this.start(true);
    178     }
    179
    180     protected String getName() {
    181         return this.name;
    182     }
    183
    184     /***
    185      * Always returns null (we override authenticate methods)
    186      *
    187      * @param arg0 DOCUMENT ME!
    188      *
    189      * @return DOCUMENT ME!
    190      */
    191     protected String getPassword(String arg0) {
    192         return null;
    193     }
    194
    195     /***
    196      * Always returns null (we override authenticate methods)
    197      *
    198      * @param arg0 DOCUMENT ME!
    199      *
    200      * @return DOCUMENT ME!
    201      */
    202     protected Principal getPrincipal(String arg0) {
    203         return null;
    204     }
    205
    206     /***
    207      * Provides a method to load the container adapter without delegating to
    208      * the superclass, which cannot operate outside the Catalina container.
    209      *
    210      * @throws LifecycleException if a problem is detected
    211      */
    212     protected void startForTest() throws LifecycleException {
    213         this.start(false);
    214     }
    215
    216     private void start(boolean startParent) throws LifecycleException {
    217         if (startParent) {
    218             super.start();
    219         }
    220
    221         if ((appContextLocation == null) || "".equals(appContextLocation)) {
    222             throw new LifecycleException("appContextLocation must be defined");
    223         }
    224
    225         if ((key == null) || "".equals(key)) {
    226             throw new LifecycleException("key must be defined");
    227         }
    228
    229         File xml = new File(System.getProperty("catalina.base"),
    230                 appContextLocation);
    231
    232         if (!xml.exists()) {
    233             throw new LifecycleException(
    234                 "appContextLocation does not seem to exist in "
    235                 + xml.toString());
    236         }
    237
    238         FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext(
    239                 "file:" + xml.getAbsolutePath());
    240         Map beans = ctx.getBeansOfType(AuthenticationManager.class, true, true);
    241
    242         if (beans.size() == 0) {
    243             throw new IllegalArgumentException(
    244                 "Bean context must contain at least one bean of type AuthenticationManager");
    245         }
    246
    247         String beanName = (String) beans.keySet().iterator().next();
    248         authenticationManager = (AuthenticationManager) beans.get(beanName);
    249         logger.info("CatalinaAcegiUserRealm Started");
    250     }
    251 }