View Javadoc

1   // ========================================================================
2   // $Id: JAASUserRealm.java 5888 2010-03-22 22:37:15Z gregw $
3   // Copyright 2003-2004 Mort Bay Consulting Pty. Ltd.
4   // ------------------------------------------------------------------------
5   // Licensed under the Apache License, Version 2.0 (the "License");
6   // you may not use this file except in compliance with the License.
7   // You may obtain a copy of the License at 
8   // http://www.apache.org/licenses/LICENSE-2.0
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.mortbay.jetty.plus.jaas;
17  
18  import java.security.Principal;
19  import java.security.acl.Group;
20  import java.util.ArrayList;
21  import java.util.Arrays;
22  import java.util.HashMap;
23  import java.util.Iterator;
24  import java.util.Set;
25  
26  import javax.security.auth.login.LoginContext;
27  import javax.security.auth.login.LoginException;
28  
29  import org.mortbay.jetty.Request;
30  import org.mortbay.jetty.plus.jaas.callback.AbstractCallbackHandler;
31  import org.mortbay.jetty.plus.jaas.callback.DefaultCallbackHandler;
32  import org.mortbay.jetty.security.UserRealm;
33  import org.mortbay.log.Log;
34  import org.mortbay.util.Loader;
35  
36  
37  
38  
39  /* ---------------------------------------------------- */
40  /** JAASUserRealm
41   * <p>
42   *
43   * <p><h4>Notes</h4>
44   * <p>
45   *
46   * <p><h4>Usage</h4>
47   * 
48   *
49   *
50   * 
51   * @org.apache.xbean.XBean element="jaasUserRealm" description="Creates a UserRealm suitable for use with JAAS"
52   */
53  public class JAASUserRealm implements UserRealm
54  {
55      public static String DEFAULT_ROLE_CLASS_NAME = "org.mortbay.jetty.plus.jaas.JAASRole";
56      public static String[] DEFAULT_ROLE_CLASS_NAMES = {DEFAULT_ROLE_CLASS_NAME};
57  	
58      protected String[] roleClassNames = DEFAULT_ROLE_CLASS_NAMES;
59      protected String callbackHandlerClass;
60      protected String realmName;
61      protected String loginModuleName;
62      protected RoleCheckPolicy roleCheckPolicy;
63      protected JAASUserPrincipal defaultUser = new JAASUserPrincipal(null, null);
64      
65   
66  
67      /* ---------------------------------------------------- */
68      /**
69       * Constructor.
70       *
71       */
72      public JAASUserRealm ()
73      {
74      }
75      
76  
77      /* ---------------------------------------------------- */
78      /**
79       * Constructor.
80       *
81       * @param name the name of the realm
82       */
83      public JAASUserRealm(String name)
84      {
85          this();
86          realmName = name;
87      }
88  
89  
90      /* ---------------------------------------------------- */
91      /**
92       * Get the name of the realm.
93       *
94       * @return name or null if not set.
95       */
96      public String getName()
97      {
98          return realmName;
99      }
100 
101 
102     /* ---------------------------------------------------- */
103     /**
104      * Set the name of the realm
105      *
106      * @param name a <code>String</code> value
107      */
108     public void setName (String name)
109     {
110         realmName = name;
111     }
112 
113 
114 
115     /**
116      * Set the name to use to index into the config
117      * file of LoginModules.
118      *
119      * @param name a <code>String</code> value
120      */
121     public void setLoginModuleName (String name)
122     {
123         loginModuleName = name;
124     }
125 
126 
127     public void setCallbackHandlerClass (String classname)
128     {
129         callbackHandlerClass = classname;
130     }
131     
132     public void setRoleClassNames (String[] classnames)
133     {
134         ArrayList tmp = new ArrayList();
135         
136         if (classnames != null)
137             tmp.addAll(Arrays.asList(classnames));
138          
139         if (!tmp.contains(DEFAULT_ROLE_CLASS_NAME))
140             tmp.add(DEFAULT_ROLE_CLASS_NAME);
141         roleClassNames = (String[])tmp.toArray(new String[tmp.size()]);
142     }
143 
144     public String[] getRoleClassNames()
145     {
146         return roleClassNames;
147     }
148     
149     public void setRoleCheckPolicy (RoleCheckPolicy policy)
150     {
151         roleCheckPolicy = policy;
152     }
153 
154     //TODO: delete?!
155     public Principal getPrincipal(String username)
156     {
157         return null;
158     }
159 
160 
161     /* ------------------------------------------------------------ */
162     public boolean isUserInRole(Principal user, String role)
163     {
164         JAASUserPrincipal thePrincipal = null;
165         
166         if (user == null)
167             thePrincipal = defaultUser;
168         else
169         {
170             if (! (user instanceof JAASUserPrincipal))
171                 return false;
172             
173             thePrincipal = (JAASUserPrincipal)user;
174         }
175         return thePrincipal!=null && thePrincipal.isUserInRole(role);
176     }
177 
178 
179     /* ------------------------------------------------------------ */
180     public boolean reauthenticate(Principal user)
181     {
182         if (user instanceof JAASUserPrincipal)
183             return true;
184         else
185             return false;
186     }
187 
188     
189     /* ---------------------------------------------------- */
190     /**
191      * Authenticate a user.
192      * 
193      *
194      * @param username provided by the user at login
195      * @param credentials provided by the user at login
196      * @param request a <code>Request</code> value
197      * @return authenticated JAASUserPrincipal or  null if authenticated failed
198      */
199     public Principal authenticate(String username,
200             Object credentials,
201             Request request)
202     {
203         try
204         {              
205             AbstractCallbackHandler callbackHandler = null;
206             
207             //user has not been authenticated
208             if (callbackHandlerClass == null)
209             {
210                 Log.warn("No CallbackHandler configured: using DefaultCallbackHandler");
211                 callbackHandler = new DefaultCallbackHandler();
212             }
213             else
214             {
215                 callbackHandler = (AbstractCallbackHandler)Loader.loadClass(JAASUserRealm.class, callbackHandlerClass).getConstructors()[0].newInstance(new Object[0]);
216             }
217             
218             if (callbackHandler instanceof DefaultCallbackHandler)
219             {
220                 ((DefaultCallbackHandler)callbackHandler).setRequest (request);
221             }
222             
223             callbackHandler.setUserName(username);
224             callbackHandler.setCredential(credentials);
225             
226             
227             //set up the login context
228             LoginContext loginContext = new LoginContext(loginModuleName,
229                     callbackHandler);
230             
231             loginContext.login();
232             
233             //login success
234             JAASUserPrincipal userPrincipal = new JAASUserPrincipal(this, username);
235             userPrincipal.setSubject(loginContext.getSubject());
236             userPrincipal.setRoleCheckPolicy (roleCheckPolicy);
237             userPrincipal.setLoginContext(loginContext);
238             
239             
240             
241             return userPrincipal;       
242         }
243         catch (Exception e)
244         {
245             Log.warn(e.toString());
246             Log.debug(e);
247             return null;
248         }     
249     }
250 
251     
252 
253     /* ---------------------------------------------------- */
254     /**
255      * Removes any auth info associated with eg. the thread.
256      *
257      * @param user a UserPrincipal to disassociate
258      */
259     public void disassociate(Principal user)
260     {
261         //TODO: should this apply to the default user?
262         if (user == null)
263             defaultUser.disassociate();
264         else
265             ((JAASUserPrincipal)user).disassociate();
266     }
267 
268     
269 
270     /* ---------------------------------------------------- */
271     /**
272      * Temporarily adds a role to a user.
273      *
274      * Temporarily granting a role pushes the role onto a stack
275      * of temporary roles. Temporary roles must therefore be
276      * removed in order.
277      *
278      * @param user the Principal to which to add the role
279      * @param role the role name
280      * @return the Principal with the role added
281      */
282     public Principal pushRole(Principal user, String role)
283     {
284         JAASUserPrincipal thePrincipal = (JAASUserPrincipal)user;
285         
286         //use the default user
287         if (thePrincipal == null)
288             thePrincipal = defaultUser;
289         
290     
291         thePrincipal.pushRole(role);
292         return thePrincipal;
293     }
294     
295     /* ------------------------------------------------------------ */
296     public Principal popRole(Principal user)
297     {
298         JAASUserPrincipal thePrincipal = (JAASUserPrincipal)user;
299         
300         //use the default user
301         if (thePrincipal == null)
302             thePrincipal = defaultUser;
303         
304         thePrincipal.popRole();
305         return thePrincipal;
306     }
307 
308 
309     public Group getRoles (JAASUserPrincipal principal)
310     {
311         //get all the roles of the various types
312         String[] roleClassNames = getRoleClassNames();
313         Group roleGroup = new JAASGroup(JAASGroup.ROLES);
314         
315         try
316         {
317             JAASUserPrincipal thePrincipal = principal;
318             
319             if (thePrincipal == null)
320                 thePrincipal = defaultUser;
321             
322             for (int i=0; i<roleClassNames.length;i++)
323             {
324                 Class load_class=Thread.currentThread().getContextClassLoader().loadClass(roleClassNames[i]);
325                 Set rolesForType = thePrincipal.getSubject().getPrincipals (load_class);
326                 Iterator itor = rolesForType.iterator();
327                 while (itor.hasNext())
328                 {
329                     roleGroup.addMember((Principal) itor.next());
330                 }
331             }
332             
333             return roleGroup;
334         }
335         catch (ClassNotFoundException e)
336         {
337             throw new RuntimeException(e);
338         }
339     }
340 
341 
342     /* ---------------------------------------------------- */
343     /**
344      * Logout a previously logged in user.
345      * This can only work for FORM authentication
346      * as BasicAuthentication is stateless.
347      * 
348      * The user's LoginContext logout() method is called.
349      * @param user an <code>Principal</code> value
350      */
351     public void logout(Principal user)
352     {
353         try
354         {
355             JAASUserPrincipal authenticUser = null;
356             
357             if (user == null)
358                 authenticUser = defaultUser; //TODO: should the default user ever be logged in?
359             
360             if (!(user instanceof JAASUserPrincipal))
361                 throw new IllegalArgumentException (user + " is not a JAASUserPrincipal");
362             
363  
364             authenticUser = (JAASUserPrincipal)user;
365  
366             authenticUser.getLoginContext().logout();
367             
368             Log.debug (user+" has been LOGGED OUT");
369         }
370         catch (LoginException e)
371         {
372             Log.warn (e);
373         }
374     }
375 
376 
377    
378     
379 }