[jboss-cvs] jboss-seam/src/main/org/jboss/seam/security ...

Shane Bryzak Shane_Bryzak at symantec.com
Thu Jan 25 08:21:37 EST 2007


  User: sbryzak2
  Date: 07/01/25 08:21:37

  Modified:    src/main/org/jboss/seam/security    Identity.java
                        SecurityFunctions.java
  Removed:     src/main/org/jboss/seam/security    Security.java
  Log:
  security API refactorings
  
  Revision  Changes    Path
  1.15      +321 -10   jboss-seam/src/main/org/jboss/seam/security/Identity.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: Identity.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/src/main/org/jboss/seam/security/Identity.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -b -r1.14 -r1.15
  --- Identity.java	23 Jan 2007 14:50:11 -0000	1.14
  +++ Identity.java	25 Jan 2007 13:21:37 -0000	1.15
  @@ -3,34 +3,73 @@
   import static org.jboss.seam.ScopeType.SESSION;
   import static org.jboss.seam.annotations.Install.BUILT_IN;
   
  +import java.io.IOException;
   import java.io.Serializable;
   import java.security.Principal;
   import java.security.acl.Group;
  +import java.security.acl.Permission;
  +import java.util.ArrayList;
  +import java.util.Enumeration;
  +import java.util.HashSet;
  +import java.util.List;
   import java.util.Set;
  +import java.util.regex.Matcher;
  +import java.util.regex.Pattern;
   
  +import javax.faces.context.FacesContext;
   import javax.security.auth.Subject;
  -
  +import javax.security.auth.callback.Callback;
  +import javax.security.auth.callback.CallbackHandler;
  +import javax.security.auth.callback.NameCallback;
  +import javax.security.auth.callback.PasswordCallback;
  +import javax.security.auth.callback.UnsupportedCallbackException;
  +import javax.security.auth.login.LoginContext;
  +import javax.security.auth.login.LoginException;
  +
  +import org.drools.FactHandle;
  +import org.drools.RuleBase;
  +import org.drools.WorkingMemory;
   import org.jboss.seam.Component;
   import org.jboss.seam.ScopeType;
  +import org.jboss.seam.Seam;
  +import org.jboss.seam.annotations.Create;
  +import org.jboss.seam.annotations.In;
   import org.jboss.seam.annotations.Install;
   import org.jboss.seam.annotations.Name;
   import org.jboss.seam.annotations.Scope;
   import org.jboss.seam.contexts.Contexts;
  +import org.jboss.seam.log.LogProvider;
  +import org.jboss.seam.log.Logging;
  +import org.jboss.seam.security.config.SecurityConfiguration;
  +import org.jboss.seam.security.config.SecurityConfiguration.Role;
  +import org.jboss.seam.security.rules.PermissionCheck;
  +import org.jboss.seam.util.UnifiedELValueBinding;
   
   @Name("org.jboss.seam.security.identity")
   @Scope(SESSION)
  - at Install(precedence = BUILT_IN, dependencies = "org.jboss.seam.securityManager")
  + at Install(precedence = BUILT_IN)
   public class Identity implements Serializable
   {  
      private static final long serialVersionUID = 3751659008033189259L;
   
  -   protected Principal principal;
  +   private String username;
  +   private String password;
      
  +   protected Principal principal;   
      protected Subject subject;
      
  -   public Identity()
  +   @In(create = true, required = false)
  +   private RuleBase securityRules;
  +   
  +   private WorkingMemory securityContext;
  +   
  +   private static final LogProvider log = Logging.getLogProvider(Identity.class);   
  +   
  +   @Create
  +   public void create()
      {
         subject = new Subject();
  +      securityContext = securityRules.newWorkingMemory(false);
      }
   
      public static Identity instance()
  @@ -105,11 +144,283 @@
       */
      public void checkRestriction(String expr)
      {
  -      if (!isLoggedIn())
  -         throw new NotLoggedInException();
  -      
  -      if (!Security.instance().evaluateExpression(expr))
  +      if (!evaluateExpression(expr))
            throw new AuthorizationException(String.format(
                  "Authorization check failed for expression [%s]", expr));      
      }
  +   
  +   public void login()
  +      throws LoginException
  +   {
  +      CallbackHandler cbh = createCallbackHandler(username, password);
  +         
  +      LoginContext lc = createLoginContext(null, cbh);
  +      lc.login();      
  +   }
  +   
  +   public void logout()
  +   {
  +      subject = new Subject();
  +   }
  +
  +   /**
  +    * Checks if the authenticated Identity is a member of the specified role.
  +    * 
  +    * @param name String The name of the role to check
  +    * @return boolean True if the user is a member of the specified role
  +    */
  +   public boolean hasRole(String name)
  +   {
  +      if (!Contexts.isSessionContextActive() || !Contexts.getSessionContext().isSet(
  +            Seam.getComponentName(Identity.class)))
  +      {
  +         return false;
  +      }
  +     
  +      return Identity.instance().isUserInRole(name);
  +   }
  +
  +   /**
  +    * Performs a permission check for the specified name and action
  +    * 
  +    * @param name String The permission name
  +    * @param action String The permission action
  +    * @param arg Object Optional object parameter used to make a permission decision
  +    * @return boolean True if the user has the specified permission
  +    */
  +   public boolean hasPermission(String name, String action, Object arg)
  +   {
  +      List<FactHandle> handles = new ArrayList<FactHandle>();
  +
  +      PermissionCheck check = new PermissionCheck(name, action);
  +
  +      handles.add(securityContext.assertObject(check));
  +
  +      if (arg != null)
  +      {
  +         handles.add(securityContext.assertObject(arg));
  +      }      
  +      
  +      // this doesn't work?
  +//      for (String nm : Contexts.getMethodContext().getNames())
  +//      {
  +//         handles.add(securityContext.assertObject(Contexts.getMethodContext().get(nm)));
  +//      }
  +
  +      securityContext.fireAllRules();
  +
  +      for (FactHandle handle : handles)
  +         securityContext.retractObject(handle);
  +      
  +      return check.isGranted();
  +   }
  +   
  +   
  +   /**
  +    * Creates a callback handler that can handle a standard username/password
  +    * callback, using the specified username and password parameters.
  +    * 
  +    * @param username The username to provide for a NameCallback
  +    * @param password The password to provide for a PasswordCallback
  +    */
  +   public CallbackHandler createCallbackHandler(final String username, 
  +         final String password)
  +   {
  +      return new CallbackHandler() {
  +         public void handle(Callback[] callbacks) 
  +            throws IOException, UnsupportedCallbackException 
  +         {
  +            for (int i = 0; i < callbacks.length; i++)
  +            {
  +               if (callbacks[i] instanceof NameCallback)
  +                  ((NameCallback) callbacks[i]).setName(username);
  +               else if (callbacks[i] instanceof PasswordCallback)
  +                  ((PasswordCallback) callbacks[i]).setPassword(password.toCharArray());
  +               else
  +                  throw new UnsupportedCallbackException(callbacks[i],
  +                        "Unsupported callback");
  +            }
  +            
  +         }
  +      };
  +   }
  +   
  +   
  +   /**
  +    * Creates a LoginContext without a callback handler
  +    * 
  +    * @throws LoginException
  +    */
  +   public LoginContext createLoginContext()
  +      throws LoginException
  +   {
  +      return createLoginContext(null, null);
  +   }
  +   
  +   /**
  +    * Creates a LoginContext using a configuration specified by name.
  +    *  
  +    * @param policyName The name of the security configuration policy to use
  +    * @throws LoginException
  +    */
  +   public LoginContext createLoginContext(String policyName)
  +      throws LoginException
  +   {
  +      return createLoginContext(policyName, null);      
  +   }
  +      
  +   /**
  +    * A factory method for creating a LoginContext instance.  Users must use this
  +    * method instead of creating their own LoginContext as this factory method
  +    * creates a LoginContext with a custom configuration and overridden login()
  +    * method.
  +    * 
  +    * @param cbHandler The callback handler provided to the LoginContext
  +    * @throws LoginException
  +    */
  +   public LoginContext createLoginContext(String policyName, CallbackHandler cbHandler)
  +       throws LoginException
  +   {     
  +      String name = policyName != null ? policyName : SecurityConfiguration.DEFAULT_LOGIN_MODULE_NAME;
  +      
  +      return new LoginContext(name, Identity.instance().getSubject(), cbHandler,
  +            SecurityConfiguration.instance().getLoginModuleConfiguration()) {
  +         @Override public void login() throws LoginException {
  +            super.login();
  +            postLogin();
  +         }
  +      };
  +   }
  +   
  +   /**
  +    * Populates the specified subject's roles with any inherited roles
  +    * according to the role memberships contained within the current 
  +    * SecurityConfiguration
  +    * 
  +    * @param subject The subject containing the role group.
  +    */
  +   private void postLogin()
  +   {
  +      // Populate the working memory with the user's principals
  +      for (Principal p : subject.getPrincipals())
  +      {         
  +         if (p instanceof Group && "roles".equals(((Group) p).getName()))
  +         {
  +            SecurityConfiguration config = SecurityConfiguration.instance();
  +            
  +            Enumeration e = ((Group) p).members();
  +            while (e.hasMoreElements())
  +            {
  +               Principal role = (Principal) e.nextElement();
  +               
  +               Role r = config.getSecurityRole(role.getName());
  +               if (r.getPermissions() != null)
  +               {
  +                  for (Permission perm : r.getPermissions())
  +                  {
  +                     securityContext.assertObject(perm);
  +                  }
  +               }
  +            }
  +         }
  +         else
  +         {
  +            securityContext.assertObject(p);            
  +         }
  +      }
  +      
  +      for (SimpleGroup grp : subject.getPrincipals(SimpleGroup.class))
  +      {
  +         if ("roles".equals(grp.getName()))
  +         {
  +            Set<Principal> memberships = new HashSet<Principal>();
  +            SecurityConfiguration config = SecurityConfiguration.instance();
  +            
  +            Enumeration e = grp.members();
  +            while (e.hasMoreElements())
  +            {
  +               Principal role = (Principal) e.nextElement();
  +               addRoleMemberships(memberships, role.getName(), config);               
  +            }
  +            
  +            for (Principal r : memberships)
  +               grp.addMember(r);
  +            
  +            break;
  +         }
  +      }
  +   }
  +   
  +   /**
  +    * Recursively adds role memberships to the specified role set, for the
  +    * specified role name.  The security configuration is passed in each time
  +    * so that a context lookup doesn't need to take place each time.
  +    * 
  +    * @param roles The set that role memberships are to be added to
  +    * @param roleName The name of the role to add memberships for
  +    * @param config The security configuration
  +    */
  +   private void addRoleMemberships(Set<Principal> roles, String roleName, 
  +         SecurityConfiguration config)
  +   {
  +      // Retrieve the role configuration
  +      Role role = config.getSecurityRole(roleName);
  +      
  +      // For each of the role's configured memberships, check if the roles
  +      // parameter already contains the membership.  If it doesn't add it,
  +      // and make a recursive call to add the membership role's memberships.
  +      for (String membership : role.getMemberships())
  +      {
  +         SimplePrincipal r = new SimplePrincipal(membership);
  +         if (!roles.contains(r))
  +         {
  +            roles.add(r);
  +            addRoleMemberships(roles, membership, config);
  +         }
  +      }      
  +   }      
  +   
  +   private static Pattern EXPR_PATTERN = Pattern.compile("(hasPermission\\s*\\(\\s*'[^']*'\\s*,\\s*'[^']*')(\\s*\\))");
  +
  +   /**
  +    * Evaluates the specified security expression, which must return a boolean
  +    * value.
  +    * 
  +    * @param expr String The expression to evaluate
  +    * @return boolean The result of the expression evaluation
  +    */
  +   public boolean evaluateExpression(String expr) 
  +       throws AuthorizationException
  +   {     
  +      // TODO Ugly hack!  Fix this once varargs work with EL      
  +      Matcher m = EXPR_PATTERN.matcher(expr);
  +      String replaced = m.replaceAll("$1, null$2");
  +      
  +      return (Boolean) new UnifiedELValueBinding(replaced).getValue(FacesContext.getCurrentInstance());
  +   }   
  +   
  +   public String getUsername()
  +   {
  +      return username;
  +   }
  +   
  +   public void setUsername(String username)
  +   {
  +      this.username = username;
  +   }
  +   
  +   public String getPassword()
  +   {
  +      return null;
  +   }
  +   
  +   public void setPassword(String password)
  +   {
  +      this.password = password;
  +   }
  +   
  +   public WorkingMemory getSecurityContext()
  +   {
  +      return securityContext;
  +   }
   }
  
  
  
  1.2       +3 -3      jboss-seam/src/main/org/jboss/seam/security/SecurityFunctions.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: SecurityFunctions.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/src/main/org/jboss/seam/security/SecurityFunctions.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -b -r1.1 -r1.2
  --- SecurityFunctions.java	23 Jan 2007 22:25:57 -0000	1.1
  +++ SecurityFunctions.java	25 Jan 2007 13:21:37 -0000	1.2
  @@ -9,12 +9,12 @@
   {
      public static boolean hasRole(String name)
      {
  -      return Security.instance().hasRole(name);
  +      return Identity.instance().hasRole(name);
      }
      
      public static boolean hasPermission(String name, String action,
  -            Object... args)
  +            Object arg)
      {
  -      return Security.instance().hasPermission(name, action, args);
  +      return Identity.instance().hasPermission(name, action, arg);
      }
   }
  
  
  



More information about the jboss-cvs-commits mailing list