Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » catalina » realm » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    * 
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    * 
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   
   18   
   19   package org.apache.catalina.realm;
   20   
   21   
   22   import java.security.Principal;
   23   import java.io.File;
   24   import java.util.ArrayList;
   25   import java.util.HashMap;
   26   import java.util.Map;
   27   import org.apache.catalina.LifecycleException;
   28   import org.apache.catalina.util.StringManager;
   29   import org.apache.juli.logging.Log;
   30   import org.apache.juli.logging.LogFactory;
   31   import org.apache.tomcat.util.digester.Digester;
   32   
   33   
   34   /**
   35    * Simple implementation of <b>Realm</b> that reads an XML file to configure
   36    * the valid users, passwords, and roles.  The file format (and default file
   37    * location) are identical to those currently supported by Tomcat 3.X.
   38    * <p>
   39    * <strong>IMPLEMENTATION NOTE</strong>: It is assumed that the in-memory
   40    * collection representing our defined users (and their roles) is initialized
   41    * at application startup and never modified again.  Therefore, no thread
   42    * synchronization is performed around accesses to the principals collection.
   43    *
   44    * @author Craig R. McClanahan
   45    * @version $Revision: 543691 $ $Date: 2007-06-02 03:37:08 +0200 (sam., 02 juin 2007) $
   46    */
   47   
   48   public class MemoryRealm  extends RealmBase {
   49   
   50       private static Log log = LogFactory.getLog(MemoryRealm.class);
   51   
   52       // ----------------------------------------------------- Instance Variables
   53   
   54   
   55       /**
   56        * The Digester we will use to process in-memory database files.
   57        */
   58       private static Digester digester = null;
   59   
   60   
   61       /**
   62        * Descriptive information about this Realm implementation.
   63        */
   64       protected final String info =
   65           "org.apache.catalina.realm.MemoryRealm/1.0";
   66   
   67   
   68       /**
   69        * Descriptive information about this Realm implementation.
   70        */
   71   
   72       protected static final String name = "MemoryRealm";
   73   
   74   
   75       /**
   76        * The pathname (absolute or relative to Catalina's current working
   77        * directory) of the XML file containing our database information.
   78        */
   79       private String pathname = "conf/tomcat-users.xml";
   80   
   81   
   82       /**
   83        * The set of valid Principals for this Realm, keyed by user name.
   84        */
   85       private Map<String,GenericPrincipal> principals =
   86           new HashMap<String,GenericPrincipal>();
   87   
   88   
   89       /**
   90        * The string manager for this package.
   91        */
   92       private static StringManager sm =
   93           StringManager.getManager(Constants.Package);
   94   
   95   
   96       // ------------------------------------------------------------- Properties
   97   
   98   
   99       /**
  100        * Return descriptive information about this Realm implementation and
  101        * the corresponding version number, in the format
  102        * <code>&lt;description&gt;/&lt;version&gt;</code>.
  103        */
  104       public String getInfo() {
  105   
  106           return info;
  107   
  108       }
  109   
  110   
  111       /**
  112        * Return the pathname of our XML file containing user definitions.
  113        */
  114       public String getPathname() {
  115   
  116           return pathname;
  117   
  118       }
  119   
  120   
  121       /**
  122        * Set the pathname of our XML file containing user definitions.  If a
  123        * relative pathname is specified, it is resolved against "catalina.base".
  124        *
  125        * @param pathname The new pathname
  126        */
  127       public void setPathname(String pathname) {
  128   
  129           this.pathname = pathname;
  130   
  131       }
  132   
  133   
  134       // --------------------------------------------------------- Public Methods
  135   
  136   
  137       /**
  138        * Return the Principal associated with the specified username and
  139        * credentials, if there is one; otherwise return <code>null</code>.
  140        *
  141        * @param username Username of the Principal to look up
  142        * @param credentials Password or other credentials to use in
  143        *  authenticating this username
  144        */
  145       public Principal authenticate(String username, String credentials) {
  146   
  147           GenericPrincipal principal =
  148               (GenericPrincipal) principals.get(username);
  149   
  150           boolean validated = false;
  151           if (principal != null) {
  152               if (hasMessageDigest()) {
  153                   // Hex hashes should be compared case-insensitive
  154                   validated = (digest(credentials)
  155                                .equalsIgnoreCase(principal.getPassword()));
  156               } else {
  157                   validated =
  158                       (digest(credentials).equals(principal.getPassword()));
  159               }
  160           }
  161   
  162           if (validated) {
  163               if (log.isDebugEnabled())
  164                   log.debug(sm.getString("memoryRealm.authenticateSuccess", username));
  165               return (principal);
  166           } else {
  167               if (log.isDebugEnabled())
  168                   log.debug(sm.getString("memoryRealm.authenticateFailure", username));
  169               return (null);
  170           }
  171   
  172       }
  173   
  174   
  175       // -------------------------------------------------------- Package Methods
  176   
  177   
  178       /**
  179        * Add a new user to the in-memory database.
  180        *
  181        * @param username User's username
  182        * @param password User's password (clear text)
  183        * @param roles Comma-delimited set of roles associated with this user
  184        */
  185       void addUser(String username, String password, String roles) {
  186   
  187           // Accumulate the list of roles for this user
  188           ArrayList<String> list = new ArrayList<String>();
  189           roles += ",";
  190           while (true) {
  191               int comma = roles.indexOf(',');
  192               if (comma < 0)
  193                   break;
  194               String role = roles.substring(0, comma).trim();
  195               list.add(role);
  196               roles = roles.substring(comma + 1);
  197           }
  198   
  199           // Construct and cache the Principal for this user
  200           GenericPrincipal principal =
  201               new GenericPrincipal(this, username, password, list);
  202           principals.put(username, principal);
  203   
  204       }
  205   
  206   
  207       // ------------------------------------------------------ Protected Methods
  208   
  209   
  210       /**
  211        * Return a configured <code>Digester</code> to use for processing
  212        * the XML input file, creating a new one if necessary.
  213        */
  214       protected synchronized Digester getDigester() {
  215   
  216           if (digester == null) {
  217               digester = new Digester();
  218               digester.setValidating(false);
  219               digester.addRuleSet(new MemoryRuleSet());
  220           }
  221           return (digester);
  222   
  223       }
  224   
  225   
  226       /**
  227        * Return a short name for this Realm implementation.
  228        */
  229       protected String getName() {
  230   
  231           return (name);
  232   
  233       }
  234   
  235   
  236       /**
  237        * Return the password associated with the given principal's user name.
  238        */
  239       protected String getPassword(String username) {
  240   
  241           GenericPrincipal principal =
  242               (GenericPrincipal) principals.get(username);
  243           if (principal != null) {
  244               return (principal.getPassword());
  245           } else {
  246               return (null);
  247           }
  248   
  249       }
  250   
  251   
  252       /**
  253        * Return the Principal associated with the given user name.
  254        */
  255       protected Principal getPrincipal(String username) {
  256   
  257           return (Principal) principals.get(username);
  258   
  259       }
  260   
  261       /**
  262        * Returns the principals for this realm.
  263        *
  264        * @return The principals, keyed by user name (a String)
  265        */
  266       protected Map getPrincipals() {
  267           return principals;
  268       }
  269   
  270   
  271       // ------------------------------------------------------ Lifecycle Methods
  272   
  273   
  274       /**
  275        * Prepare for active use of the public methods of this Component.
  276        *
  277        * @exception LifecycleException if this component detects a fatal error
  278        *  that prevents it from being started
  279        */
  280       public synchronized void start() throws LifecycleException {
  281   
  282           // Perform normal superclass initialization
  283           super.start();
  284   
  285           // Validate the existence of our database file
  286           File file = new File(pathname);
  287           if (!file.isAbsolute())
  288               file = new File(System.getProperty("catalina.base"), pathname);
  289           if (!file.exists() || !file.canRead())
  290               throw new LifecycleException
  291                   (sm.getString("memoryRealm.loadExist",
  292                                 file.getAbsolutePath()));
  293   
  294           // Load the contents of the database file
  295           if (log.isDebugEnabled())
  296               log.debug(sm.getString("memoryRealm.loadPath",
  297                                file.getAbsolutePath()));
  298           Digester digester = getDigester();
  299           try {
  300               synchronized (digester) {
  301                   digester.push(this);
  302                   digester.parse(file);
  303               }
  304           } catch (Exception e) {
  305               throw new LifecycleException
  306                   (sm.getString("memoryRealm.readXml"), e);
  307           } finally {
  308               digester.reset();
  309           }
  310   
  311       }
  312   
  313   
  314       /**
  315        * Gracefully shut down active use of the public methods of this Component.
  316        *
  317        * @exception LifecycleException if this component detects a fatal error
  318        *  that needs to be reported
  319        */
  320       public synchronized void stop() throws LifecycleException {
  321   
  322           // Perform normal superclass finalization
  323           super.stop();
  324   
  325           // No shutdown activities required
  326   
  327       }
  328   
  329   
  330   }

Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » catalina » realm » [javadoc | source]