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

Shane Bryzak Shane_Bryzak at symantec.com
Tue Jan 23 17:25:57 EST 2007


  User: sbryzak2
  Date: 07/01/23 17:25:57

  Added:       src/main/org/jboss/seam/security   Security.java
                        SecurityFunctions.java
  Log:
  oops
  
  Revision  Changes    Path
  1.1      date: 2007/01/23 22:25:57;  author: sbryzak2;  state: Exp;jboss-seam/src/main/org/jboss/seam/security/Security.java
  
  Index: Security.java
  ===================================================================
  package org.jboss.seam.security;
  
  import static org.jboss.seam.ScopeType.APPLICATION;
  import static org.jboss.seam.annotations.Install.BUILT_IN;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  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.RuleBaseFactory;
  import org.drools.WorkingMemory;
  import org.drools.compiler.PackageBuilder;
  import org.drools.compiler.PackageBuilderConfiguration;
  import org.jboss.seam.Component;
  import org.jboss.seam.InterceptionType;
  import org.jboss.seam.ScopeType;
  import org.jboss.seam.Seam;
  import org.jboss.seam.annotations.Create;
  import org.jboss.seam.annotations.Install;
  import org.jboss.seam.annotations.Intercept;
  import org.jboss.seam.annotations.Name;
  import org.jboss.seam.annotations.Scope;
  import org.jboss.seam.annotations.Startup;
  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.Resources;
  import org.jboss.seam.util.UnifiedELValueBinding;
  
  /**
   * Holds configuration settings and provides functionality for the security API
   * 
   * @author Shane Bryzak
   */
  @Startup(depends = "org.jboss.seam.security.securityConfiguration")
  @Scope(APPLICATION)
  @Name("org.jboss.seam.security")
  @Install(value = false, precedence = BUILT_IN)
  @Intercept(InterceptionType.NEVER)
  public class Security
  {
     private static final String SECURITY_RULES_FILENAME = "/META-INF/security-rules.drl";
  
     private static final String SECURITY_CONTEXT_NAME = "org.jboss.seam.security.securityContext";
  
     private static final LogProvider log = Logging
           .getLogProvider(Security.class);
  
     private RuleBase securityRules;
  
     /**
      * Initialise the security manager
      * 
      * @throws Exception
      */
     @Create
     public void initSecurity() throws Exception
     {
        // Create the security rule base
        PackageBuilderConfiguration conf = new PackageBuilderConfiguration();
        conf.setCompiler(PackageBuilderConfiguration.JANINO);
  
        securityRules = RuleBaseFactory.newRuleBase();
        InputStream in = Resources.getResourceAsStream(SECURITY_RULES_FILENAME);
        if (in != null)
        {
           PackageBuilder builder = new PackageBuilder(conf);
           builder.addPackageFromDrl(new InputStreamReader(in));
           securityRules.addPackage(builder.getPackage());
        }
        else
           log.warn(String.format("Security rules file %s not found",
                 SECURITY_RULES_FILENAME));
     }
  
     /**
      * Returns the application-scoped instance of the security manager
      * 
      * @return SeamSecurityManager The application-scoped instance of the SecurityManager
      */
     public static Security instance()
     {
        if (!Contexts.isApplicationContextActive())
           throw new IllegalStateException("No active application context");
  
        Security instance = (Security) Component
              .getInstance(Security.class, ScopeType.APPLICATION);
  
        if (instance == null)
        {
           throw new IllegalStateException(
                 "No SeamSecurityManager could be created, make sure the Component exists in application scope");
        }
  
        return instance;
     }
     
     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());
     }
  
     /**
      * 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 args Object[] Optional number of objects used to make a permission decision
      * @return boolean True if the user has the specified permission
      */
     public boolean hasPermission(String name, String action,
           Object... args)
     {
        Security mgr = instance();
  
        List<FactHandle> handles = new ArrayList<FactHandle>();
  
        PermissionCheck check = new PermissionCheck(name, action);
  
        WorkingMemory wm = mgr.getWorkingMemoryForSession();
        handles.add(wm.assertObject(check));
  
        if (args != null)
        {
           for (Object o : args)
           {
              if (o != null)
                handles.add(wm.assertObject(o));
           }
        }      
  
        wm.fireAllRules();
  
        for (FactHandle handle : handles)
           wm.retractObject(handle);
  
        return check.isGranted();
     }
  
     /**
      * Returns the security working memory for the current session
      * 
      * @return WorkingMemory
      */
     private WorkingMemory getWorkingMemoryForSession()
     {
        if (!Contexts.isSessionContextActive())
           throw new IllegalStateException("No active session context found.");
        
        if (Contexts.getSessionContext().isSet(SECURITY_CONTEXT_NAME))
           return (WorkingMemory) Contexts.getSessionContext().get(SECURITY_CONTEXT_NAME);
        else         
        {
           WorkingMemory wm = securityRules.newWorkingMemory();
    
           if (Identity.instance().isLoggedIn())
           {
              for (Principal p : Identity.instance().getSubject().getPrincipals())
              {
                 wm.assertObject(p);
                 
                 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())
                          {
                             wm.assertObject(perm);
                          }
                       }
                    }
                 }
              }
              
              // Only set the security context if the user is already logged in            
              Contexts.getSessionContext().set(SECURITY_CONTEXT_NAME, wm);
           }
           
           return wm;
        }
     }
     
     /**
      * 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();
              populateRoles(this.getSubject());
           }
        };
     }
     
     /**
      * 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 populateRoles(Subject subject)
     {
        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);
           }
        }
        
     }
     
     /**
      * 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");
              }
              
           }
        };
     }
  }
  
  
  
  1.1      date: 2007/01/23 22:25:57;  author: sbryzak2;  state: Exp;jboss-seam/src/main/org/jboss/seam/security/SecurityFunctions.java
  
  Index: SecurityFunctions.java
  ===================================================================
  package org.jboss.seam.security;
  
  /**
   * Delegating wrapper for EL security functions.
   * 
   * @author Shane Bryzak
   */
  public class SecurityFunctions
  {
     public static boolean hasRole(String name)
     {
        return Security.instance().hasRole(name);
     }
     
     public static boolean hasPermission(String name, String action,
              Object... args)
     {
        return Security.instance().hasPermission(name, action, args);
     }
  }
  
  
  



More information about the jboss-cvs-commits mailing list