View Javadoc

    1   /* Copyright 2004, 2005 Acegi Technology Pty Limited
    2    *
    3    * Licensed under the Apache License, Version 2.0 (the "License");
    4    * you may not use this file except in compliance with the License.
    5    * You may obtain a copy of the License at
    6    *
    7    *     http://www.apache.org/licenses/LICENSE-2.0
    8    *
    9    * Unless required by applicable law or agreed to in writing, software
    10   * distributed under the License is distributed on an "AS IS" BASIS,
    11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12   * See the License for the specific language governing permissions and
    13   * limitations under the License.
    14   */
    15
    16  package org.acegisecurity.adapters.jboss;
    17
    18  import org.acegisecurity.Authentication;
    19  import org.acegisecurity.context.SecurityContextHolder;
    20
    21  import org.apache.commons.logging.Log;
    22  import org.apache.commons.logging.LogFactory;
    23
    24  import java.io.IOException;
    25
    26  import java.security.Principal;
    27
    28  import java.util.Iterator;
    29
    30  import javax.naming.Context;
    31  import javax.naming.InitialContext;
    32  import javax.naming.NamingException;
    33
    34  import javax.security.auth.Subject;
    35
    36  import javax.servlet.Filter;
    37  import javax.servlet.FilterChain;
    38  import javax.servlet.FilterConfig;
    39  import javax.servlet.ServletException;
    40  import javax.servlet.ServletRequest;
    41  import javax.servlet.ServletResponse;
    42
    43
    44  /***
    45   * Populates a {@link org.acegisecurity.context.security.SecureContext} from
    46   * JBoss' <code>java:comp/env/security/subject</code>.
    47   *
    48   * <p>
    49   * This filter <b>never</b> preserves the <code>Authentication</code> on the
    50   * <code>ContextHolder</code> - it is replaced every request.
    51   * </p>
    52   *
    53   * <p>
    54   * See {@link HttpSessionContextIntegrationFilter} for further information.
    55   * </p>
    56   *
    57   * @author Ben Alex
    58   * @version $Id: JbossIntegrationFilter.java,v 1.11 2005/11/17 00:56:29 benalex Exp $
    59   */
    60  public class JbossIntegrationFilter implements Filter {
    61      //~ Static fields/initializers =============================================
    62
    63      private static final Log logger = LogFactory.getLog(JbossIntegrationFilter.class);
    64
    65      //~ Methods ================================================================
    66
    67      /***
    68       * Does nothing. We use IoC container lifecycle services instead.
    69       */
    70      public void destroy() {}
    71
    72      public void doFilter(ServletRequest request, ServletResponse response,
    73          FilterChain chain) throws IOException, ServletException {
    74          Object principal = extractFromContainer(request);
    75
    76          if ((principal != null) && principal instanceof Authentication) {
    77              SecurityContextHolder.getContext().setAuthentication((Authentication) principal);
    78
    79              if (logger.isDebugEnabled()) {
    80                  logger.debug(
    81                      "ContextHolder updated with Authentication from container: '"
    82                      + principal + "'");
    83              }
    84          } else {
    85              if (logger.isDebugEnabled()) {
    86                  logger.debug(
    87                      "ContextHolder not set with new Authentication as Principal was: '"
    88                      + principal + "'");
    89              }
    90          }
    91
    92          chain.doFilter(request, response);
    93      }
    94
    95      /***
    96       * Does nothing. We use IoC container lifecycle services instead.
    97       *
    98       * @param arg0 ignored
    99       *
    100      * @throws ServletException ignored
    101      */
    102     public void init(FilterConfig arg0) throws ServletException {}
    103
    104     /***
    105      * Provided so that unit tests can override.
    106      *
    107      * @return a <code>Context</code> that can be used for lookup
    108      *
    109      * @throws NamingException DOCUMENT ME!
    110      */
    111     protected Context getLookupContext() throws NamingException {
    112         return new InitialContext();
    113     }
    114
    115     private Object extractFromContainer(ServletRequest request) {
    116         Subject subject = null;
    117
    118         try {
    119             Context lc = this.getLookupContext();
    120
    121             if (lc == null) {
    122                 if (logger.isWarnEnabled()) {
    123                     logger.warn("Could not obtain a Context to perform lookup");
    124                 }
    125
    126                 return null;
    127             }
    128
    129             Object result = lc.lookup("java:comp/env/security/subject");
    130
    131             if (result instanceof Subject) {
    132                 subject = (Subject) result;
    133             }
    134         } catch (NamingException ne) {
    135             if (logger.isWarnEnabled()) {
    136                 logger.warn("Lookup on Subject failed "
    137                     + ne.getLocalizedMessage());
    138             }
    139         }
    140
    141         if ((subject != null) && (subject.getPrincipals() != null)) {
    142             Iterator principals = subject.getPrincipals().iterator();
    143
    144             while (principals.hasNext()) {
    145                 Principal p = (Principal) principals.next();
    146
    147                 if (p instanceof Authentication) {
    148                     return p;
    149                 }
    150             }
    151         }
    152
    153         return null;
    154     }
    155 }