Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/catalina/realm/UserDatabaseRealm.java


1   /*
2    * Copyright 2002,2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  
18  package org.apache.catalina.realm;
19  
20  
21  import java.security.Principal;
22  import java.util.ArrayList;
23  import java.util.Iterator;
24  import java.util.List;
25  
26  import javax.naming.Context;
27  
28  import org.apache.catalina.Group;
29  import org.apache.catalina.LifecycleException;
30  import org.apache.catalina.Role;
31  import org.apache.catalina.ServerFactory;
32  import org.apache.catalina.User;
33  import org.apache.catalina.UserDatabase;
34  import org.apache.catalina.core.StandardServer;
35  import org.apache.catalina.users.MemoryUser;
36  import org.apache.catalina.util.StringManager;
37  
38  
39  /**
40   * <p>Implementation of {@link org.apache.catalina.Realm} that is based on an implementation of
41   * {@link UserDatabase} made available through the global JNDI resources
42   * configured for this instance of Catalina.  Set the <code>resourceName</code>
43   * parameter to the global JNDI resources name for the configured instance
44   * of <code>UserDatabase</code> that we should consult.</p>
45   *
46   * @author Craig R. McClanahan
47   * @version $Revision: 304062 $ $Date: 2005-08-18 00:41:02 -0400 (Thu, 18 Aug 2005) $
48   * @since 4.1
49   */
50  
51  public class UserDatabaseRealm
52      extends RealmBase {
53  
54  
55      // ----------------------------------------------------- Instance Variables
56  
57  
58      /**
59       * The <code>UserDatabase</code> we will use to authenticate users
60       * and identify associated roles.
61       */
62      protected UserDatabase database = null;
63  
64  
65      /**
66       * Descriptive information about this Realm implementation.
67       */
68      protected final String info =
69          "org.apache.catalina.realm.UserDatabaseRealm/1.0";
70  
71  
72      /**
73       * Descriptive information about this Realm implementation.
74       */
75      protected static final String name = "UserDatabaseRealm";
76  
77  
78      /**
79       * The global JNDI name of the <code>UserDatabase</code> resource
80       * we will be utilizing.
81       */
82      protected String resourceName = "UserDatabase";
83  
84  
85      /**
86       * The string manager for this package.
87       */
88      private static StringManager sm =
89          StringManager.getManager(Constants.Package);
90  
91  
92      // ------------------------------------------------------------- Properties
93  
94  
95      /**
96       * Return descriptive information about this Realm implementation and
97       * the corresponding version number, in the format
98       * <code>&lt;description&gt;/&lt;version&gt;</code>.
99       */
100     public String getInfo() {
101 
102         return info;
103 
104     }
105 
106 
107     /**
108      * Return the global JNDI name of the <code>UserDatabase</code> resource
109      * we will be using.
110      */
111     public String getResourceName() {
112 
113         return resourceName;
114 
115     }
116 
117 
118     /**
119      * Set the global JNDI name of the <code>UserDatabase</code> resource
120      * we will be using.
121      *
122      * @param resourceName The new global JNDI name
123      */
124     public void setResourceName(String resourceName) {
125 
126         this.resourceName = resourceName;
127 
128     }
129 
130 
131     // --------------------------------------------------------- Public Methods
132 
133 
134     /**
135      * Return <code>true</code> if the specified Principal has the specified
136      * security role, within the context of this Realm; otherwise return
137      * <code>false</code>. This implementation returns <code>true</code>
138      * if the <code>User</code> has the role, or if any <code>Group</code>
139      * that the <code>User</code> is a member of has the role. 
140      *
141      * @param principal Principal for whom the role is to be checked
142      * @param role Security role to be checked
143      */
144     public boolean hasRole(Principal principal, String role) {
145         if( principal instanceof GenericPrincipal) {
146             GenericPrincipal gp = (GenericPrincipal)principal;
147             if(gp.getUserPrincipal() instanceof User) {
148                 principal = gp.getUserPrincipal();
149             }
150         }
151         if(! (principal instanceof User) ) {
152             //Play nice with SSO and mixed Realms
153             return super.hasRole(principal, role);
154         }
155         if("*".equals(role)) {
156             return true;
157         } else if(role == null) {
158             return false;
159         }
160         User user = (User)principal;
161         Role dbrole = database.findRole(role);
162         if(dbrole == null) {
163             return false; 
164         }
165         if(user.isInRole(dbrole)) {
166             return true;
167         }
168         Iterator groups = user.getGroups();
169         while(groups.hasNext()) {
170             Group group = (Group)groups.next();
171             if(group.isInRole(dbrole)) {
172                 return true;
173             }
174         }
175         return false;
176     }
177     
178     // ------------------------------------------------------ Protected Methods
179 
180 
181     /**
182      * Return a short name for this Realm implementation.
183      */
184     protected String getName() {
185 
186         return (name);
187 
188     }
189 
190 
191     /**
192      * Return the password associated with the given principal's user name.
193      */
194     protected String getPassword(String username) {
195 
196         User user = database.findUser(username);
197 
198         if (user == null) {
199             return null;
200         } 
201 
202         return (user.getPassword());
203 
204     }
205 
206 
207     /**
208      * Return the Principal associated with the given user name.
209      */
210     protected Principal getPrincipal(String username) {
211 
212         User user = database.findUser(username);
213         if(user == null) {
214             return null;
215         }
216 
217         List roles = new ArrayList();
218         Iterator uroles = user.getRoles();
219         while(uroles.hasNext()) {
220             Role role = (Role)uroles.next();
221             roles.add(role.getName());
222         }
223         Iterator groups = user.getGroups();
224         while(groups.hasNext()) {
225             Group group = (Group)groups.next();
226             uroles = user.getRoles();
227             while(uroles.hasNext()) {
228                 Role role = (Role)uroles.next();
229                 roles.add(role.getName());
230             }
231         }
232         return new GenericPrincipal(this, username, user.getPassword(), roles, user);
233     }
234 
235 
236     // ------------------------------------------------------ Lifecycle Methods
237 
238 
239     /**
240      * Prepare for active use of the public methods of this Component.
241      *
242      * @exception LifecycleException if this component detects a fatal error
243      *  that prevents it from being started
244      */
245     public synchronized void start() throws LifecycleException {
246 
247         try {
248             StandardServer server = (StandardServer) ServerFactory.getServer();
249             Context context = server.getGlobalNamingContext();
250             database = (UserDatabase) context.lookup(resourceName);
251         } catch (Throwable e) {
252             containerLog.error(sm.getString("userDatabaseRealm.lookup",
253                                             resourceName),
254                                e);
255             database = null;
256         }
257         if (database == null) {
258             throw new LifecycleException
259                 (sm.getString("userDatabaseRealm.noDatabase", resourceName));
260         }
261 
262         // Perform normal superclass initialization
263         super.start();
264 
265     }
266 
267 
268     /**
269      * Gracefully shut down active use of the public methods of this Component.
270      *
271      * @exception LifecycleException if this component detects a fatal error
272      *  that needs to be reported
273      */
274     public synchronized void stop() throws LifecycleException {
275 
276         // Perform normal superclass finalization
277         super.stop();
278 
279         // Release reference to our user database
280         database = null;
281 
282     }
283 
284 
285 }