Save This Page
Home » jboss-5.0.0.CR1-src » org » jboss » net » axis » server » [javadoc | source]
    1   /*
    2    * JBoss, the OpenSource J2EE webOS
    3    *
    4    * Distributable under LGPL license.
    5    * See terms of license at gnu.org.
    6    */
    7   
    8   // $Id: JBossAuthorizationHandler.java,v 1.1 2002/03/15 10:04:24 cgjung Exp $
    9   
   10   package org.jboss.net.axis.server;
   11   
   12   import org.apache.axis.AxisFault;
   13   import org.apache.axis.handlers.BasicHandler;
   14   import org.apache.axis.MessageContext;
   15   
   16   import org.jboss.security.SimplePrincipal;
   17   import org.jboss.security.AnybodyPrincipal;
   18   import org.jboss.security.NobodyPrincipal;
   19   import org.jboss.security.RealmMapping;
   20   
   21   import javax.naming.InitialContext;
   22   import javax.naming.NamingException;
   23   
   24   import java.security.Principal;
   25   import javax.security.auth.Subject;
   26   
   27   import java.util.StringTokenizer;
   28   import java.util.Set;
   29   import java.util.Iterator;
   30   import java.util.Collection;
   31   import java.util.Collections;
   32   
   33   /**
   34    * AuthorizationHandler that checks allowed and denied roles against the active
   35    * subject using a given realmMapping. Is somehow redundant to what, e.g., the JBoss EJB invocation handler
   36    * does, but maybe we need this to shield access to other container resources
   37    * such as MBeans for which we will expose security-agnostic providers.
   38    * <br>
   39    * <h3>Change History</h3>
   40    * <ul>
   41    * <li> jung, 15.03.2002: Added security domain option. </li>
   42    * </ul>
   43    * <br>
   44    * <h3>To Do</h3>
   45    * <ul>
   46    * <li> jung, 14.03.2002: Cache simple principals. Principal factory for
   47    * interacting with various security domains.
   48    * </ul>
   49    * @author <a href="mailto:Christoph.Jung@infor.de">Christoph G. Jung</a>
   50    * @created 14.03.2002
   51    * @version $Revision: 1.1 $
   52    */
   53   
   54   public class JBossAuthorizationHandler extends BasicHandler {
   55   
   56      //
   57      // Attributes
   58      //
   59   
   60      /** the security domain against which we call */
   61      protected RealmMapping realmMapping;
   62      /** the roles that we want to let through */
   63      final protected Set rolesAllowed = new java.util.HashSet();
   64      /** the roles that we want to deny access */
   65      final protected Set rolesDenied = new java.util.HashSet();
   66      /** whether this handler has been initialized */
   67      protected boolean isInitialised;
   68   
   69      //
   70      // Constructors
   71      //
   72   
   73      public JBossAuthorizationHandler() {
   74      }
   75   
   76      //
   77      // Protected helpers
   78      //
   79   
   80      /** initializes the roles checked by this handler */
   81      protected void initialise() throws AxisFault {
   82         // bind against the jboss security subsystem
   83         isInitialised = true;
   84         realmMapping = null;
   85         String securityDomain = (String) getOption(Constants.SECURITY_DOMAIN_OPTION);
   86         if (securityDomain != null) {
   87            try {
   88               realmMapping =
   89                  (RealmMapping) new InitialContext().lookup(securityDomain);
   90            } catch (NamingException e) {
   91               throw new AxisFault("Could not lookup security domain " + securityDomain, e);
   92            }
   93         }
   94   
   95         // parse role options 
   96         String allowedRoles = (String) getOption(Constants.ALLOWED_ROLES_OPTION);
   97   
   98         // default:let all through 
   99         if (allowedRoles == null) {
  100            allowedRoles = "*";
  101         }
  102   
  103         StringTokenizer tokenizer = new StringTokenizer(allowedRoles, ",");
  104         while (tokenizer.hasMoreTokens()) {
  105            rolesAllowed.add(getPrincipal(tokenizer.nextToken()));
  106         }
  107   
  108         String deniedRoles = (String) getOption(Constants.DENIED_ROLES_OPTION);
  109         if (deniedRoles != null) {
  110            tokenizer = new StringTokenizer(deniedRoles, ",");
  111            while (tokenizer.hasMoreTokens()) {
  112               rolesDenied.add(getPrincipal(tokenizer.nextToken()));
  113            }
  114         }
  115      }
  116   
  117      /** 
  118       * creates a new principal belonging to the given username,
  119       * override to adapt to specific security domains.
  120       */
  121      protected Principal getPrincipal(String userName) {
  122         if (userName.equals("*")) {
  123            return AnybodyPrincipal.ANYBODY_PRINCIPAL;
  124         } else {
  125            return new SimplePrincipal(userName);
  126         }
  127      }
  128   
  129      /** returns a collection of principals that the context subject
  130       *  is associated with
  131       */
  132      protected Collection getAssociatedPrincipals(MessageContext msgContext) {
  133         // get the active subject
  134         Subject activeSubject =
  135            (Subject) msgContext.getProperty(MessageContext.AUTHUSER);
  136         if (activeSubject == null) {
  137            return Collections.singleton(NobodyPrincipal.NOBODY_PRINCIPAL);
  138         } else {
  139            return activeSubject.getPrincipals();
  140         }
  141      }
  142   
  143      /** return whether the given Principal has the given roles */
  144      protected boolean doesUserHaveRole(Principal principal, Set roles) {
  145         return realmMapping.doesUserHaveRole(principal, roles);
  146      }
  147   
  148      //
  149      // API
  150      //
  151   
  152      /**
  153       * Authenticate the user and password from the msgContext. Note that
  154       * we do not disassociate the subject here, since that would have
  155       * to be done by a separate handler in the response chain and we
  156       * currently expect Jetty or the WebContainer to do that for us
  157       */
  158   
  159      public void invoke(MessageContext msgContext) throws AxisFault {
  160   
  161         // initialize the handler
  162         if (!isInitialised) {
  163            synchronized (this) {
  164               if (!isInitialised) {
  165                  initialise();
  166               }
  167            }
  168         }
  169   
  170         // check association
  171         if (realmMapping == null) {
  172            throw new AxisFault("No security domain associated.");
  173         }
  174   
  175         Iterator allPrincipals = getAssociatedPrincipals(msgContext).iterator();
  176         boolean accessAllowed = false;
  177         while (allPrincipals.hasNext()) {
  178            Principal nextPrincipal = (Principal) allPrincipals.next();
  179            // a single denied is enough to exclude the access
  180            if (doesUserHaveRole(nextPrincipal, rolesDenied)) {
  181               accessAllowed = false;
  182               break;
  183               // allowed
  184            } else if (!accessAllowed && doesUserHaveRole(nextPrincipal, rolesAllowed)) {
  185               accessAllowed = true;
  186            }
  187         }
  188   
  189         if (!accessAllowed) {
  190            throw new AxisFault("Access denied.");
  191         }
  192      }
  193   }

Save This Page
Home » jboss-5.0.0.CR1-src » org » jboss » net » axis » server » [javadoc | source]