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 }