[jboss-cvs] jbosssx/src/main/org/jboss/security/plugins ...

Anil Saldhana anil.saldhana at jboss.com
Fri Jul 14 14:40:36 EDT 2006


  User: asaldhana
  Date: 06/07/14 14:40:36

  Modified:    src/main/org/jboss/security/plugins   Tag:
                        JBoss_4_0_2_JBAS-977 JaasSecurityManager.java
                        SubjectActions.java
  Log:
  JBAS-3397: Remove the synchronization on the isValid method
  
  Revision  Changes    Path
  No                   revision
  
  
  No                   revision
  
  
  1.41.2.4.42.1 +122 -45   jbosssx/src/main/org/jboss/security/plugins/JaasSecurityManager.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: JaasSecurityManager.java
  ===================================================================
  RCS file: /cvsroot/jboss/jbosssx/src/main/org/jboss/security/plugins/JaasSecurityManager.java,v
  retrieving revision 1.41.2.4
  retrieving revision 1.41.2.4.42.1
  diff -u -b -r1.41.2.4 -r1.41.2.4.42.1
  --- JaasSecurityManager.java	17 Feb 2005 00:14:07 -0000	1.41.2.4
  +++ JaasSecurityManager.java	14 Jul 2006 18:40:36 -0000	1.41.2.4.42.1
  @@ -1,5 +1,5 @@
   /*
  - * JBoss, the OpenSource EJB server
  + * JBoss, Home of Professional Open Source 
    *
    * Distributable under LGPL license.
    * See terms of license at gnu.org.
  @@ -37,13 +37,13 @@
    domain name associated with the class for authentication,
    and the context JAAS Subject object for role mapping.
    
  - @see #isValid(Principal, Object)
  + @see #isValid(Principal, Object, Subject)
    @see #getPrincipal(Principal)
    @see #doesUserHaveRole(Principal, Set)
    
    @author <a href="on at ibis.odessa.ua">Oleg Nitz</a>
    @author Scott.Stark at jboss.org
  - @version $Revision: 1.41.2.4 $
  + @version $Revision: 1.41.2.4.42.1 $
   */
   public class JaasSecurityManager extends ServiceMBeanSupport 
      implements SubjectSecurityManager, RealmMapping
  @@ -59,11 +59,47 @@
         private Object credential;
         private Principal callerPrincipal;
         private long expirationTime;
  +      /** Is there an active authentication in process */ 
  +      private boolean needsDestroy; 
  +      /** The number of users sharing this DomainInfo */ 
  +      private int activeUsers; 
   
         public DomainInfo(int lifetime)
         {
            expirationTime = 1000 * lifetime;
         }
  +      
  +      synchronized int acquire() 
  +      { 
  +         return activeUsers ++; 
  +      } 
  +      synchronized int release() 
  +      { 
  +         int users = activeUsers --; 
  +         if( needsDestroy == true && users == 0 ) 
  +         { 
  +            if( trace ) 
  +               log.trace("needsDestroy is true, doing logout"); 
  +            logout(); 
  +         } 
  +         return users; 
  +      } 
  +      synchronized void logout() 
  +      { 
  +         if( trace ) 
  +            log.trace("logout, subject="+subject+", this="+this); 
  +         try 
  +         { 
  +            if( loginCtx != null ) 
  +               loginCtx.logout(); 
  +         } 
  +         catch(Throwable e) 
  +         { 
  +            if( trace ) 
  +               log.trace("Cache entry logout failed", e); 
  +         } 
  +      }
  +      
         public void init(long now)
         {
            expirationTime += now;
  @@ -79,15 +115,18 @@
         public void destroy()
         {
            if( trace )
  -            log.trace("destroy, subject="+subject+", this="+this);
  -         try
  +    		  log.trace("destroy, subject="+subject+", this="+this 
  +    				  +", activeUsers="+activeUsers); 
  +    	  synchronized( this ) 
            {
  -            loginCtx.logout();
  -         }
  -         catch(Exception e)
  +    		  if( activeUsers == 0 ) 
  +    			  logout(); 
  +    		  else 
            {
               if( trace )
  -               log.trace("Cache entry logout failed", e);
  +    				  log.trace("destroy saw activeUsers="+activeUsers); 
  +    			  needsDestroy = true; 
  +    		  }  
            }
         }
         public Object getValue()
  @@ -98,10 +137,7 @@
         {
            StringBuffer tmp = new StringBuffer(super.toString());
            tmp.append('[');
  -         tmp.append("Subject(");
  -         tmp.append(System.identityHashCode(subject));
  -         tmp.append(").principals=");
  -         tmp.append(subject.getPrincipals());
  +         tmp.append(SubjectActions.toString(subject)); 
            tmp.append(",credential.class=");
            if( credential != null )
            {
  @@ -173,12 +209,13 @@
            String msg = "Failed to find setSecurityInfo(Princpal, Object) method in handler";
            throw new UndeclaredThrowableException(e, msg);
         }
  +      log.debug("CallbackHandler: "+handler);
      }
   
      /** 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)
  +    @see #isValid(Principal, Object, Subject)
       */
      public void setCachePolicy(CachePolicy domainCache)
      {
  @@ -210,6 +247,10 @@
       */
      public Subject getActiveSubject()
      {
  +	 /* This does not use SubjectActions.getActiveSubject since the caller 
  +       must have the correct permissions to access the 
  +       SecurityAssociation.getSubject method. 
  +     */
         return SecurityAssociation.getSubject();
      }
   
  @@ -236,17 +277,22 @@
         the state of the authenticated Subject.
       @return true if the principal was authenticated, false otherwise.
       */
  -   public synchronized boolean isValid(Principal principal, Object credential,
  +   public boolean isValid(Principal principal, Object credential,
         Subject activeSubject)
      {
         // Check the cache first
         DomainInfo cacheInfo = getCacheInfo(principal, true);
         if( trace )
  -         log.trace("Begin isValid, cache info: "+cacheInfo);
  +    	  log.trace("Begin isValid, principal:"+principal+", cache info: "+cacheInfo); 
   
         boolean isValid = false;
         if( cacheInfo != null )
  +      {
            isValid = validateCache(cacheInfo, credential, activeSubject);
  +    	  if( cacheInfo != null ) 
  +              cacheInfo.release();
  +      }
  +         
         if( isValid == false )
            isValid = authenticate(principal, credential, activeSubject);
         if( trace )
  @@ -277,6 +323,7 @@
               // If the mapping did not have a callerPrincipal just use principal
               if( result == null )
                  result = principal;
  +            info.release(); 
            }
         }
   
  @@ -285,9 +332,13 @@
   
      /** 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.
  +    the principal set of the currently authenticated Subject as determined 
  +    by the SecurityAssociation.getSubject() method 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. This requires that the caller 
  +    establish the correct SecurityAssociation subject prior to calling this 
  +    method. In the past this was done as a side-effect of an isValid() call, 
  +    but this is no longer the case. 
       @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.
  @@ -316,6 +367,8 @@
               {
                  Principal role = (Principal) iter.next();
                  hasRole = doesRoleGroupHaveRole(role, roles);
  +               if( trace ) 
  +                   log.trace("hasRole("+role+")="+hasRole); 
               }
            }
            if( trace )
  @@ -324,11 +377,16 @@
         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.
  +   /** Does the current Subject have a role(a Principal) that equates to one 
  +   of the role names. 
  +
  +   @see #doesUserHaveRole(Principal, Set) 
  +
  +   @param principal - ignored. The current authenticated Subject determines 
  +   the active user and assigned user roles. 
  +   @param role - the application domain role that the principal is to be 
  +     validated against. 
  +   @return true if the active principal has the role, false otherwise. 
       */
      public boolean doesUserHaveRole(Principal principal, Principal role)
      {
  @@ -350,7 +408,11 @@
         return hasRole;
      }
   
  -   /** Return the set of domain roles the principal has been assigned.
  +   /** Return the set of domain roles the current active Subject 'Roles' group 
  +       found in the subject Principals set. 
  +
  +       @param principal - ignored. The current authenticated Subject determines 
  +       the active user and assigned user roles. 
      @return The Set<Principal> for the application domain roles that the
      principal has been assigned.
      */
  @@ -464,23 +526,34 @@
      private LoginContext defaultLogin(Principal principal, Object credential)
         throws LoginException
      {
  -      // We use our internal CallbackHandler to provide the security info
  +	  /* We use our internal CallbackHandler to provide the security info. A 
  +	      copy must be made to ensure there is a unique handler per active 
  +	      login since there can be multiple active logins. 
  +	     */ 
         Object[] securityInfo = {principal, credential};
  +      CallbackHandler theHandler = null; 
         try
         {
  -         setSecurityInfo.invoke(handler, securityInfo);
  +    	  theHandler = (CallbackHandler) handler.getClass().newInstance(); 
  +          setSecurityInfo.invoke(theHandler, securityInfo); 
         }
  -      catch (Exception e)
  +      catch (Throwable  e)
         {
            if( trace )
               log.trace("Failed to setSecurityInfo on handler", e);
  -         throw new LoginException("Failed to setSecurityInfo on handler, msg="
  -            + e.getMessage());
  +         log.trace("Failed to create/setSecurityInfo on handler", e); 
  +         LoginException le = new LoginException("Failed to setSecurityInfo on handler"); 
  +         le.initCause(e); 
  +         throw le; 
         }
         Subject subject = new Subject();
         LoginContext lc = null;
  -      lc = SubjectActions.createLoginContext(securityDomain, subject, handler);
  +      if( trace ) 
  +          log.trace("defaultLogin, principal="+principal); 
  +      lc = SubjectActions.createLoginContext(securityDomain, subject, theHandler); 
         lc.login();
  +      if( trace ) 
  +          log.trace("defaultLogin, lc="+lc+", subject="+SubjectActions.toString(subject));
         return lc;
      }
   
  @@ -569,10 +642,9 @@
      /** An accessor method that synchronizes access on the domainCache
       to avoid a race condition that can occur when the cache entry expires
       in the presence of multi-threaded access. The allowRefresh flag should
  -    be true for authentication accesses and false for authorization accesses.
  -    If it were to be true for an authorization access a previously authenticated
  -    user could be seen to not have their expected permissions due to a cache
  -    expiration.
  +    be true for authentication accesses and false for other accesses. 
  +    Previously the other accesses included authorization and caller principal 
  +    mapping. Now the only use of the  
   
       @param principal - the caller identity whose cached credentials are to
       be accessed.
  @@ -591,6 +663,8 @@
               cacheInfo = (DomainInfo) domainCache.get(principal);
             else
               cacheInfo = (DomainInfo) domainCache.peek(principal);
  +          if( cacheInfo != null ) 
  +              cacheInfo.acquire(); 
         }
         return cacheInfo;
      }
  @@ -615,7 +689,10 @@
         info.credential = credential;
   
         if( trace )
  -         log.trace("updateCache, subject="+subject);
  +      { 
  +          log.trace("updateCache, inputSubject="+SubjectActions.toString(subject) 
  +             +", cacheSubject="+SubjectActions.toString(info.subject)); 
  +       } 
   
        /* Get the Subject callerPrincipal by looking for a Group called
           'CallerPrincipal'
  
  
  
  1.3.2.4.42.1 +40 -1     jbosssx/src/main/org/jboss/security/plugins/SubjectActions.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: SubjectActions.java
  ===================================================================
  RCS file: /cvsroot/jboss/jbosssx/src/main/org/jboss/security/plugins/SubjectActions.java,v
  retrieving revision 1.3.2.4
  retrieving revision 1.3.2.4.42.1
  diff -u -b -r1.3.2.4 -r1.3.2.4.42.1
  --- SubjectActions.java	6 Apr 2005 21:16:55 -0000	1.3.2.4
  +++ SubjectActions.java	14 Jul 2006 18:40:36 -0000	1.3.2.4.42.1
  @@ -27,6 +27,35 @@
    */
   class SubjectActions
   {
  +	private static class ToStringSubjectAction implements PrivilegedAction 
  +	   { 
  +	      Subject subject; 
  +	      ToStringSubjectAction(Subject subject) 
  +	      { 
  +	         this.subject = subject; 
  +	      } 
  +	      public Object run() 
  +	      { 
  +	         StringBuffer tmp = new StringBuffer(); 
  +	         tmp.append("Subject("); 
  +	         tmp.append(System.identityHashCode(subject)); 
  +	         tmp.append(").principals="); 
  +	         Iterator principals = subject.getPrincipals().iterator(); 
  +	         while( principals.hasNext() ) 
  +	         { 
  +	            Object p = principals.next(); 
  +	            Class c = p.getClass(); 
  +	            tmp.append(c.getName()); 
  +	            tmp.append('@'); 
  +	            tmp.append(System.identityHashCode(c)); 
  +	            tmp.append('('); 
  +	            tmp.append(p); 
  +	            tmp.append(')'); 
  +	         } 
  +	         return tmp.toString(); 
  +	      } 
  +	   } 
  +	
      private static class GetSubjectAction implements PrivilegedAction
      {
         static PrivilegedAction ACTION = new GetSubjectAction();
  @@ -176,7 +205,10 @@
      static void copySubject(Subject fromSubject, Subject toSubject, boolean setReadOnly)
      {
         CopySubjectAction action = new CopySubjectAction(fromSubject, toSubject, setReadOnly);
  +      if( System.getSecurityManager() != null ) 
         AccessController.doPrivileged(action);
  +       else 
  +          action.run(); 
      }
   
      static LoginContext createLoginContext(String securityDomain, Subject subject,
  @@ -236,5 +268,12 @@
         }
      }
   
  +   static String toString(Subject subject) 
  +   { 
  +      ToStringSubjectAction action = new ToStringSubjectAction(subject); 
  +      String info = (String) AccessController.doPrivileged(action); 
  +      return info; 
  +   } 
  +
   }
   
  
  
  



More information about the jboss-cvs-commits mailing list