View Javadoc

    1   // ========================================================================
    2   // $Id: JAASUserRealm.java 1001 2006-09-23 09:31:51Z janb $
    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 ((JAASUserPrincipal)user).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 }