User: starksm
Date: 01/07/14 09:50:56
Modified: src/main/org/jboss/security/plugins Tag: Branch_2_4
JaasSecurityManager.java
Log:
Clean up multiple return paths from validateCache to ensure that any
valid credential results in the active subject being associated with
the current thread
Revision Changes Path
No revision
No revision
1.7.2.2 +476 -472
jbosssx/src/main/org/jboss/security/plugins/JaasSecurityManager.java
Index: JaasSecurityManager.java
===================================================================
RCS file:
/cvsroot/jboss/jbosssx/src/main/org/jboss/security/plugins/JaasSecurityManager.java,v
retrieving revision 1.7.2.1
retrieving revision 1.7.2.2
diff -u -r1.7.2.1 -r1.7.2.2
--- JaasSecurityManager.java 2001/07/09 08:49:37 1.7.2.1
+++ JaasSecurityManager.java 2001/07/14 16:50:56 1.7.2.2
@@ -1,472 +1,476 @@
-/*
- * JBoss, the OpenSource EJB server
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package org.jboss.security.plugins;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.Set;
-
-import java.security.AccessController;
-import java.security.Principal;
-import java.security.acl.Group;
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
-import javax.security.auth.Policy;
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-
-import org.jboss.security.AppPolicy;
-import org.jboss.security.AuthenticationInfo;
-import org.jboss.security.EJBSecurityManager;
-import org.jboss.security.RealmMapping;
-import org.jboss.security.SecurityAssociation;
-import org.jboss.security.SecurityPolicy;
-import org.jboss.security.SimplePrincipal;
-import org.jboss.security.SubjectSecurityManager;
-import org.jboss.security.auth.callback.SecurityAssociationHandler;
-import org.jboss.util.CachePolicy;
-import org.jboss.util.TimedCachePolicy;
-
-/** The JaasSecurityManager is responsible both for authenticating credentials
-associated with principals and for role mapping. This implementation relies
-on the JAAS LoginContext/LoginModules associated with the security
-domain name associated with the class for authentication,
-and the context JAAS Subject object for role mapping.
-
-@see #isValid(Principal, Object)
-@see #Principal getPrincipal(Principal)
-@see #doesUserHaveRole(Principal, Set)
-
-@author <a href="[EMAIL PROTECTED]">Oleg Nitz</a>
-@author [EMAIL PROTECTED]
-@version $Revision: 1.7.2.1 $
-*/
-public class JaasSecurityManager implements SubjectSecurityManager, RealmMapping
-{
- /** The authentication cache object.
- */
- public static class DomainInfo
- {
- Subject subject;
- Object credential;
- Principal callerPrincipal;
- Group roles;
- }
-
- /** The current authenticate()d subject.
- */
- private static ThreadLocal activeSubject = new ThreadLocal();
- /** The name of the domain this instance is securing. It is used as
- the appName into the SecurityPolicy.
- */
- private String securityDomain;
- /** A cache of DomainInfo objects keyd by Principal.
- */
- private CachePolicy domainCache;
- /** The custom JAAS policy. This may be null if a custom
- policy is not being used.
- */
- private SecurityPolicy securityPolicy;
- /** Used in the absence of a SecurityPolicy specific CallbackHandler
- to pass credential info to the LoginModule associated with the
- securityDomain name.
- */
- private SecurityAssociationHandler handler = new SecurityAssociationHandler();
-
- /** Get the currently authenticated Subject in securityDomain.
- @return The Subject for securityDomain if one exists, false otherwise.
- */
- public static Subject getActiveSubject(String securityDomain)
- {
- Subject subject = null;
- try
- {
- InitialContext ctx = new InitialContext();
- String jsmName = "jaas:/"+securityDomain;
- JaasSecurityManager jsm = (JaasSecurityManager) ctx.lookup(jsmName);
- subject = jsm.getActiveSubject();
- }
- catch(NamingException e)
- {
- }
- return subject;
- }
- /** Create a LoginContext for the currently authenticated Subject in
- securityDomain.
- */
- public static LoginContext getActiveSubjectLoginContext(String securityDomain,
CallbackHandler handler)
- throws LoginException
- {
- LoginContext lc = null;
- Subject subject = getActiveSubject(securityDomain);
- if( subject == null )
- throw new LoginException("No active subject found in securityDomain:
"+securityDomain);
-
- if( handler != null )
- lc = new LoginContext(securityDomain, subject, handler);
- else
- lc = new LoginContext(securityDomain, subject);
-
- return lc;
- }
-
- /** Creates a default JaasSecurityManager for with a securityDomain
- name of 'other'.
- */
- public JaasSecurityManager()
- {
- this("other");
- }
- /** Creates a JaasSecurityManager for with a securityDomain
- name of that given by the 'securityDomain' argument.
- @param securityDomain.
- */
- public JaasSecurityManager(String securityDomain)
- {
- this.securityDomain = securityDomain;
- try
- { // Try to get the SecurityPolicy from the JAAS Policy class
- securityPolicy = (SecurityPolicy) Policy.getPolicy();
- }
- catch(ClassCastException e)
- { // The installed Policy is not a SecurityPolicy
- }
- }
-
- /** The domainCache is typically a shared object that is populated
- by the login code(LoginModule, etc.) and read by this class in the
- isValid() method.
- @see #isValid(Principal, Object)
- */
- public void setCachePolicy(CachePolicy domainCache)
- {
- this.domainCache = domainCache;
- }
-
- public void flushCache()
- {
- if( domainCache != null )
- domainCache.flush();
- }
-
- public void setSecurityPolicyName(String jndiName) throws NamingException
- {
- InitialContext ctx = new InitialContext();
- securityPolicy = (SecurityPolicy) ctx.lookup(jndiName);
- }
-
- /** Get the name of the security domain associated with this security mgr.
- @return Name of the security manager security domain.
- */
- public String getSecurityDomain()
- {
- return securityDomain;
- }
- /** Get the currently authenticated Subject. This is a thread local
- property shared across all JaasSecurityManager instances.
- @return The Subject authenticated in the current thread if one
- exists, null otherwise.
- */
- public Subject getActiveSubject()
- {
- return (Subject) activeSubject.get();
- }
-
- /** Validate that the given credential is correct for principal. This first
- will check the current CachePolicy object if one exists to see if the
- user's cached credentials match the given credential. If there is no
- credential cache or the cache information is invalid or does not match,
- the user is authenticated against the JAAS login modules configured for
- the security domain.
- @param principal, the security domain principal attempting access
- @param credential, the proof of identity offered by the principal
- @return true if the principal was authenticated, false otherwise.
- */
- public boolean isValid(Principal principal, Object credential)
- {
- // Check the cache first
- DomainInfo cacheInfo = null;
- if( domainCache != null )
- cacheInfo = (DomainInfo) domainCache.get(principal);
-
- boolean isValid = false;
- if( cacheInfo != null )
- isValid = validateCache(cacheInfo, credential);
- if( isValid == false )
- isValid = authenticate(principal, credential);
- return isValid;
- }
-
- /** Map the argument principal from the deployment environment principal
- to the developer environment. This is called by the EJB context
- getCallerPrincipal() to return the Principal as described by
- the EJB developer domain.
- @return a Principal object that is valid in the deployment environment
- if one exists. If no Subject exists or the Subject has no principals
- then the argument principal is returned.
- */
- public Principal getPrincipal(Principal principal)
- {
- Principal result = principal;
- if( domainCache != null )
- {
- // Get the CallerPrincipal group member
- DomainInfo info = (DomainInfo) domainCache.get(principal);
- if( info != null )
- result = info.callerPrincipal;
- // If the mapping did not have a callerPrincipal just use principal
- if( result == null )
- result = principal;
- }
-
- return result;
- }
-
- /** Does the current Subject have a role(a Principal) that equates to one
- of the role names. This method obtains the Group named 'Roles' from
- the principal set of the currently authenticated Subject and then
- creates a SimplePrincipal for each name in roleNames. If the role is
- a member of the Roles group, then the user has the role.
- @param principal, ignored. The current authenticated Subject determines
- the active user and assigned user roles.
- @param rolePrincipals, a Set of Principals for the roles to check.
-
- @see java.security.acl.Group;
- @see Subject#getPrincipals()
- */
- public boolean doesUserHaveRole(Principal principal, Set rolePrincipals)
- {
- boolean hasRole = false;
- Subject subject = getActiveSubject();
- if( subject != null )
- {
- DomainInfo info = null;
- if( domainCache != null )
- info = (DomainInfo) domainCache.get(principal);
-
- Group roles = null;
- if( info != null )
- roles = info.roles;
- if( roles != null )
- {
- Iterator iter = rolePrincipals.iterator();
- while( hasRole == false && iter.hasNext() )
- {
- Principal role = (Principal) iter.next();
- hasRole = roles.isMember(role);
- }
- }
- }
- return hasRole;
- }
-
- /** Validates operational environment Principal against the specified
- application domain role.
- @param principal, the caller principal as known in the operation environment.
- @param role, the application domain role that the principal is to be validated
against.
- @return true if the principal has the role, false otherwise.
- */
- public boolean doesUserHaveRole(Principal principal, Principal role)
- {
- boolean hasRole = false;
- Subject subject = getActiveSubject();
- if( subject != null )
- {
- DomainInfo info = null;
- if( domainCache != null )
- info = (DomainInfo) domainCache.get(principal);
-
- Group roles = null;
- if( info != null )
- roles = info.roles;
- if( roles != null )
- {
- hasRole = roles.isMember(role);
- }
- }
- return hasRole;
- }
-
- /** Currently this simply calls defaultLogin() to do a JAAS login using the
- security domain name as the login module configuration name.
-
- * @param principal, the user id to authenticate
- * @param credential, an opaque credential.
- * @return false on failure, true on success.
- */
- private boolean authenticate(Principal principal, Object credential)
- {
- LoginContext lc = null;
- Subject subject = null;
- boolean authenticated = false;
-
- try
- {
- // Clear any current subject
- activeSubject.set(null);
- // Get the AppPolicy login info. Not implemented yet.
- AppPolicy policy = null;
- subject = defaultLogin(principal, credential);
-
- // Set the current subject if login was successful
- if( subject != null )
- {
- activeSubject.set(subject);
- authenticated = true;
- // Build the Subject based DomainInfo cache value
- updateCache(subject, principal, credential);
- }
- }
- catch(LoginException e)
- {
- e.printStackTrace();
- }
-
- return authenticated;
- }
-
- /** Pass the security info to the login modules configured for
- this security domain using our SecurityAssociationHandler.
- @return The authenticated Subject if successful.
- @exception LoginException throw if login fails for any reason.
- */
- private Subject defaultLogin(Principal principal, Object credential)
- throws LoginException
- {
- // We use our internal CallbackHandler to provide the security info
- handler.setSecurityInfo(principal, credential);
- Subject subject = new Subject();
- LoginContext lc = new LoginContext(securityDomain, subject, handler);
- lc.login();
- return subject;
- }
-
- /** Validate the cache credential value against the provided credential
- */
- private boolean validateCache(DomainInfo info, Object credential)
- {
- Object subjectCredential = info.credential;
- boolean isValid = false;
- // Check for a null credential as can be the case for an anonymou user
- if( credential == null )
- {
- // Subject credential must also be null
- isValid = subjectCredential == null;
- }
- if( isValid == true )
- return true;
-
- if( subjectCredential.getClass().isAssignableFrom(credential.getClass()) ==
false )
- return false;
-
- if( subjectCredential instanceof Comparable )
- {
- Comparable c = (Comparable) subjectCredential;
- isValid = c.compareTo(credential) == 0;
- }
- else if( subjectCredential instanceof char[] )
- {
- char[] a1 = (char[]) subjectCredential;
- char[] a2 = (char[]) credential;
- isValid = Arrays.equals(a1, a2);
- }
- else if( subjectCredential instanceof byte[] )
- {
- byte[] a1 = (byte[]) subjectCredential;
- byte[] a2 = (byte[]) credential;
- isValid = Arrays.equals(a1, a2);
- }
- else
- {
- isValid = subjectCredential.equals(credential);
- }
-
- if( isValid )
- {
- activeSubject.set(info.subject);
- }
-
- return isValid;
- }
-
- private void updateCache(Subject subject, Principal principal, Object
credential)
- {
- DomainInfo info = new DomainInfo();
- info.subject = subject;
- info.credential = credential;
-
- /* If we don't have a cache policy create a default timed cache
- that has an 1800 sec lifetime, is thread-safe, and a resolution
- of 60 seconds.
- */
- if( domainCache == null )
- {
- domainCache = new TimedCachePolicy(1800, true, 60);
- try
- {
- domainCache.init();
- domainCache.start();
- }
- catch(Exception e)
- {
- e.printStackTrace();
- }
- }
-
- /* Get the Subject callerPrincipal by looking for a Group called
- 'CallerPrincipal' and roles by looking for a Group called 'Roles'
- */
- Set subjectGroups = subject.getPrincipals(Group.class);
- Iterator iter = subjectGroups.iterator();
- while( iter.hasNext() )
- {
- Group grp = (Group) iter.next();
- String name = grp.getName();
- if( name.equals("CallerPrincipal") )
- {
- Enumeration members = grp.members();
- if( members.hasMoreElements() )
- info.callerPrincipal = (Principal) members.nextElement();
- }
- else if( name.equals("Roles") )
- info.roles = grp;
- }
-
- /* Handle null principals with no callerPrincipal. This is an indication
- of an user that has not provided any authentication info, but
- has been authenticated by the domain login module stack. Here we look
- for the first non-Group Principal and use that.
- */
- if( principal == null && info.callerPrincipal == null )
- {
- Set subjectPrincipals = subject.getPrincipals(Principal.class);
- iter = subjectPrincipals.iterator();
- while( iter.hasNext() )
- {
- Principal p = (Principal) iter.next();
- if( (p instanceof Group) == false )
- info.callerPrincipal = p;
- }
- }
-
- /* If the user already exists another login is active. Currently
- only one is allowed so remove the old and insert the new.
- */
- if( domainCache.peek(principal) != null )
- domainCache.remove(principal);
- domainCache.insert(principal, info);
- }
-
-}
+/*
+ * JBoss, the OpenSource EJB server
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package org.jboss.security.plugins;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Set;
+
+import java.security.AccessController;
+import java.security.Principal;
+import java.security.acl.Group;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.security.auth.Policy;
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.jboss.security.AppPolicy;
+import org.jboss.security.AuthenticationInfo;
+import org.jboss.security.EJBSecurityManager;
+import org.jboss.security.RealmMapping;
+import org.jboss.security.SecurityAssociation;
+import org.jboss.security.SecurityPolicy;
+import org.jboss.security.SimplePrincipal;
+import org.jboss.security.SubjectSecurityManager;
+import org.jboss.security.auth.callback.SecurityAssociationHandler;
+import org.jboss.util.CachePolicy;
+import org.jboss.util.TimedCachePolicy;
+
+/** The JaasSecurityManager is responsible both for authenticating credentials
+associated with principals and for role mapping. This implementation relies
+on the JAAS LoginContext/LoginModules associated with the security
+domain name associated with the class for authentication,
+and the context JAAS Subject object for role mapping.
+
+@see #isValid(Principal, Object)
+@see #Principal getPrincipal(Principal)
+@see #doesUserHaveRole(Principal, Set)
+
+@author <a href="[EMAIL PROTECTED]">Oleg Nitz</a>
+@author [EMAIL PROTECTED]
+@version $Revision: 1.7.2.2 $
+*/
+public class JaasSecurityManager implements SubjectSecurityManager, RealmMapping
+{
+ /** The authentication cache object.
+ */
+ public static class DomainInfo
+ {
+ Subject subject;
+ Object credential;
+ Principal callerPrincipal;
+ Group roles;
+ }
+
+ /** The current authenticate()d subject.
+ */
+ private static ThreadLocal activeSubject = new ThreadLocal();
+ /** The name of the domain this instance is securing. It is used as
+ the appName into the SecurityPolicy.
+ */
+ private String securityDomain;
+ /** A cache of DomainInfo objects keyd by Principal.
+ */
+ private CachePolicy domainCache;
+ /** The custom JAAS policy. This may be null if a custom
+ policy is not being used.
+ */
+ private SecurityPolicy securityPolicy;
+ /** Used in the absence of a SecurityPolicy specific CallbackHandler
+ to pass credential info to the LoginModule associated with the
+ securityDomain name.
+ */
+ private SecurityAssociationHandler handler = new SecurityAssociationHandler();
+
+ /** Get the currently authenticated Subject in securityDomain.
+ @return The Subject for securityDomain if one exists, false otherwise.
+ */
+ public static Subject getActiveSubject(String securityDomain)
+ {
+ Subject subject = null;
+ try
+ {
+ InitialContext ctx = new InitialContext();
+ String jsmName = "jaas:/"+securityDomain;
+ JaasSecurityManager jsm = (JaasSecurityManager) ctx.lookup(jsmName);
+ subject = jsm.getActiveSubject();
+ }
+ catch(NamingException e)
+ {
+ }
+ return subject;
+ }
+ /** Create a LoginContext for the currently authenticated Subject in
+ securityDomain.
+ */
+ public static LoginContext getActiveSubjectLoginContext(String securityDomain,
CallbackHandler handler)
+ throws LoginException
+ {
+ LoginContext lc = null;
+ Subject subject = getActiveSubject(securityDomain);
+ if( subject == null )
+ throw new LoginException("No active subject found in securityDomain:
"+securityDomain);
+
+ if( handler != null )
+ lc = new LoginContext(securityDomain, subject, handler);
+ else
+ lc = new LoginContext(securityDomain, subject);
+
+ return lc;
+ }
+
+ /** Creates a default JaasSecurityManager for with a securityDomain
+ name of 'other'.
+ */
+ public JaasSecurityManager()
+ {
+ this("other");
+ }
+ /** Creates a JaasSecurityManager for with a securityDomain
+ name of that given by the 'securityDomain' argument.
+ @param securityDomain.
+ */
+ public JaasSecurityManager(String securityDomain)
+ {
+ this.securityDomain = securityDomain;
+ try
+ { // Try to get the SecurityPolicy from the JAAS Policy class
+ securityPolicy = (SecurityPolicy) Policy.getPolicy();
+ }
+ catch(ClassCastException e)
+ { // The installed Policy is not a SecurityPolicy
+ }
+ }
+
+ /** The domainCache is typically a shared object that is populated
+ by the login code(LoginModule, etc.) and read by this class in the
+ isValid() method.
+ @see #isValid(Principal, Object)
+ */
+ public void setCachePolicy(CachePolicy domainCache)
+ {
+ this.domainCache = domainCache;
+ }
+
+ public void flushCache()
+ {
+ if( domainCache != null )
+ domainCache.flush();
+ }
+
+ public void setSecurityPolicyName(String jndiName) throws NamingException
+ {
+ InitialContext ctx = new InitialContext();
+ securityPolicy = (SecurityPolicy) ctx.lookup(jndiName);
+ }
+
+ /** Get the name of the security domain associated with this security mgr.
+ @return Name of the security manager security domain.
+ */
+ public String getSecurityDomain()
+ {
+ return securityDomain;
+ }
+ /** Get the currently authenticated Subject. This is a thread local
+ property shared across all JaasSecurityManager instances.
+ @return The Subject authenticated in the current thread if one
+ exists, null otherwise.
+ */
+ public Subject getActiveSubject()
+ {
+ return (Subject) activeSubject.get();
+ }
+
+ /** Validate that the given credential is correct for principal. This first
+ will check the current CachePolicy object if one exists to see if the
+ user's cached credentials match the given credential. If there is no
+ credential cache or the cache information is invalid or does not match,
+ the user is authenticated against the JAAS login modules configured for
+ the security domain.
+ @param principal, the security domain principal attempting access
+ @param credential, the proof of identity offered by the principal
+ @return true if the principal was authenticated, false otherwise.
+ */
+ public boolean isValid(Principal principal, Object credential)
+ {
+ // Check the cache first
+ DomainInfo cacheInfo = null;
+ if( domainCache != null )
+ cacheInfo = (DomainInfo) domainCache.get(principal);
+
+ boolean isValid = false;
+ if( cacheInfo != null )
+ isValid = validateCache(cacheInfo, credential);
+ if( isValid == false )
+ isValid = authenticate(principal, credential);
+ return isValid;
+ }
+
+ /** Map the argument principal from the deployment environment principal
+ to the developer environment. This is called by the EJB context
+ getCallerPrincipal() to return the Principal as described by
+ the EJB developer domain.
+ @return a Principal object that is valid in the deployment environment
+ if one exists. If no Subject exists or the Subject has no principals
+ then the argument principal is returned.
+ */
+ public Principal getPrincipal(Principal principal)
+ {
+ Principal result = principal;
+ if( domainCache != null )
+ {
+ // Get the CallerPrincipal group member
+ DomainInfo info = (DomainInfo) domainCache.get(principal);
+ if( info != null )
+ result = info.callerPrincipal;
+ // If the mapping did not have a callerPrincipal just use principal
+ if( result == null )
+ result = principal;
+ }
+
+ return result;
+ }
+
+ /** Does the current Subject have a role(a Principal) that equates to one
+ of the role names. This method obtains the Group named 'Roles' from
+ the principal set of the currently authenticated Subject and then
+ creates a SimplePrincipal for each name in roleNames. If the role is
+ a member of the Roles group, then the user has the role.
+ @param principal, ignored. The current authenticated Subject determines
+ the active user and assigned user roles.
+ @param rolePrincipals, a Set of Principals for the roles to check.
+
+ @see java.security.acl.Group;
+ @see Subject#getPrincipals()
+ */
+ public boolean doesUserHaveRole(Principal principal, Set rolePrincipals)
+ {
+ boolean hasRole = false;
+ Subject subject = getActiveSubject();
+ if( subject != null )
+ {
+ DomainInfo info = null;
+ if( domainCache != null )
+ info = (DomainInfo) domainCache.get(principal);
+
+ Group roles = null;
+ if( info != null )
+ roles = info.roles;
+ if( roles != null )
+ {
+ Iterator iter = rolePrincipals.iterator();
+ while( hasRole == false && iter.hasNext() )
+ {
+ Principal role = (Principal) iter.next();
+ hasRole = roles.isMember(role);
+ }
+ }
+ }
+ return hasRole;
+ }
+
+ /** Validates operational environment Principal against the specified
+ application domain role.
+ @param principal, the caller principal as known in the operation environment.
+ @param role, the application domain role that the principal is to be validated
against.
+ @return true if the principal has the role, false otherwise.
+ */
+ public boolean doesUserHaveRole(Principal principal, Principal role)
+ {
+ boolean hasRole = false;
+ Subject subject = getActiveSubject();
+ if( subject != null )
+ {
+ DomainInfo info = null;
+ if( domainCache != null )
+ info = (DomainInfo) domainCache.get(principal);
+
+ Group roles = null;
+ if( info != null )
+ roles = info.roles;
+ if( roles != null )
+ {
+ hasRole = roles.isMember(role);
+ }
+ }
+ return hasRole;
+ }
+
+ /** Currently this simply calls defaultLogin() to do a JAAS login using the
+ security domain name as the login module configuration name.
+
+ * @param principal, the user id to authenticate
+ * @param credential, an opaque credential.
+ * @return false on failure, true on success.
+ */
+ private boolean authenticate(Principal principal, Object credential)
+ {
+ LoginContext lc = null;
+ Subject subject = null;
+ boolean authenticated = false;
+
+ try
+ {
+ // Clear any current subject
+ activeSubject.set(null);
+ // Get the AppPolicy login info. Not implemented yet.
+ AppPolicy policy = null;
+ subject = defaultLogin(principal, credential);
+
+ // Set the current subject if login was successful
+ if( subject != null )
+ {
+ activeSubject.set(subject);
+ authenticated = true;
+ // Build the Subject based DomainInfo cache value
+ updateCache(subject, principal, credential);
+ }
+ }
+ catch(LoginException e)
+ {
+ e.printStackTrace();
+ }
+
+ return authenticated;
+ }
+
+ /** Pass the security info to the login modules configured for
+ this security domain using our SecurityAssociationHandler.
+ @return The authenticated Subject if successful.
+ @exception LoginException throw if login fails for any reason.
+ */
+ private Subject defaultLogin(Principal principal, Object credential)
+ throws LoginException
+ {
+ // We use our internal CallbackHandler to provide the security info
+ handler.setSecurityInfo(principal, credential);
+ Subject subject = new Subject();
+ LoginContext lc = new LoginContext(securityDomain, subject, handler);
+ lc.login();
+ return subject;
+ }
+
+ /** Validate the cache credential value against the provided credential
+ */
+ private boolean validateCache(DomainInfo info, Object credential)
+ {
+ Object subjectCredential = info.credential;
+ boolean isValid = false;
+ // Check for a null credential as can be the case for an anonymou user
+ if( credential == null )
+ {
+ // Subject credential must also be null
+ isValid = subjectCredential == null;
+ }
+ // See if the credential is assignable to the cache value
+ else if(
subjectCredential.getClass().isAssignableFrom(credential.getClass()) == false )
+ isValid = false;
+ else
+ {
+ /* Validate the credential by trying Comparable, char[], byte[],
+ and finally Object.equals()
+ */
+ if( subjectCredential instanceof Comparable )
+ {
+ Comparable c = (Comparable) subjectCredential;
+ isValid = c.compareTo(credential) == 0;
+ }
+ else if( subjectCredential instanceof char[] )
+ {
+ char[] a1 = (char[]) subjectCredential;
+ char[] a2 = (char[]) credential;
+ isValid = Arrays.equals(a1, a2);
+ }
+ else if( subjectCredential instanceof byte[] )
+ {
+ byte[] a1 = (byte[]) subjectCredential;
+ byte[] a2 = (byte[]) credential;
+ isValid = Arrays.equals(a1, a2);
+ }
+ else
+ {
+ isValid = subjectCredential.equals(credential);
+ }
+ }
+
+ // If the credentials match set the thread's active Subject
+ if( isValid )
+ {
+ activeSubject.set(info.subject);
+ }
+
+ return isValid;
+ }
+
+ private void updateCache(Subject subject, Principal principal, Object
credential)
+ {
+ DomainInfo info = new DomainInfo();
+ info.subject = subject;
+ info.credential = credential;
+
+ /* If we don't have a cache policy create a default timed cache
+ that has an 1800 sec lifetime, is thread-safe, and a resolution
+ of 60 seconds.
+ */
+ if( domainCache == null )
+ {
+ domainCache = new TimedCachePolicy(1800, true, 60);
+ try
+ {
+ domainCache.init();
+ domainCache.start();
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ /* Get the Subject callerPrincipal by looking for a Group called
+ 'CallerPrincipal' and roles by looking for a Group called 'Roles'
+ */
+ Set subjectGroups = subject.getPrincipals(Group.class);
+ Iterator iter = subjectGroups.iterator();
+ while( iter.hasNext() )
+ {
+ Group grp = (Group) iter.next();
+ String name = grp.getName();
+ if( name.equals("CallerPrincipal") )
+ {
+ Enumeration members = grp.members();
+ if( members.hasMoreElements() )
+ info.callerPrincipal = (Principal) members.nextElement();
+ }
+ else if( name.equals("Roles") )
+ info.roles = grp;
+ }
+
+ /* Handle null principals with no callerPrincipal. This is an indication
+ of an user that has not provided any authentication info, but
+ has been authenticated by the domain login module stack. Here we look
+ for the first non-Group Principal and use that.
+ */
+ if( principal == null && info.callerPrincipal == null )
+ {
+ Set subjectPrincipals = subject.getPrincipals(Principal.class);
+ iter = subjectPrincipals.iterator();
+ while( iter.hasNext() )
+ {
+ Principal p = (Principal) iter.next();
+ if( (p instanceof Group) == false )
+ info.callerPrincipal = p;
+ }
+ }
+
+ /* If the user already exists another login is active. Currently
+ only one is allowed so remove the old and insert the new.
+ */
+ if( domainCache.peek(principal) != null )
+ domainCache.remove(principal);
+ domainCache.insert(principal, info);
+ }
+
+}
_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-development