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.ui.rememberme;
17  
18  import org.acegisecurity.context.SecurityContextHolder;
19  import org.acegisecurity.event.authentication.InteractiveAuthenticationSuccessEvent;
20  import org.acegisecurity.Authentication;
21  
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  
25  import org.springframework.beans.factory.InitializingBean;
26  
27  import org.springframework.context.ApplicationEventPublisher;
28  import org.springframework.context.ApplicationEventPublisherAware;
29  
30  import org.springframework.util.Assert;
31  
32  import java.io.IOException;
33  
34  import javax.servlet.Filter;
35  import javax.servlet.FilterChain;
36  import javax.servlet.FilterConfig;
37  import javax.servlet.ServletException;
38  import javax.servlet.ServletRequest;
39  import javax.servlet.ServletResponse;
40  import javax.servlet.http.HttpServletRequest;
41  import javax.servlet.http.HttpServletResponse;
42  
43  
44  /***
45   * Detects if there is no <code>Authentication</code> object in the
46   * <code>SecurityContext</code>, and populates it with a remember-me
47   * authentication token if a {@link
48   * org.acegisecurity.ui.rememberme.RememberMeServices} implementation so
49   * requests.
50   * 
51   * <p>
52   * Concrete <code>RememberMeServices</code> implementations will have their
53   * {@link
54   * org.acegisecurity.ui.rememberme.RememberMeServices#autoLogin(HttpServletRequest,
55   * HttpServletResponse)} method called by this filter. The
56   * <code>Authentication</code> or <code>null</code> returned by that method
57   * will be placed into the <code>SecurityContext</code>.
58   * </p>
59   * 
60   * <p>
61   * If authentication is successful, an {@link
62   * org.acegisecurity.event.authentication.InteractiveAuthenticationSuccessEvent} will be
63   * published to the application context. No events will be published if
64   * authentication was unsuccessful, because this would generally be recorded
65   * via an <code>AuthenticationManager</code>-specific application event.
66   * </p>
67   * 
68   * <p>
69   * <b>Do not use this class directly.</b> Instead configure
70   * <code>web.xml</code> to use the {@link
71   * org.acegisecurity.util.FilterToBeanProxy}.
72   * </p>
73   *
74   * @author Ben Alex
75   * @version $Id: RememberMeProcessingFilter.java,v 1.10 2005/11/17 00:56:09 benalex Exp $
76   */
77  public class RememberMeProcessingFilter implements Filter, InitializingBean,
78          ApplicationEventPublisherAware {
79      //~ Static fields/initializers =============================================
80  
81      private static final Log logger = LogFactory.getLog(RememberMeProcessingFilter.class);
82  
83      //~ Instance fields ========================================================
84  
85      private ApplicationEventPublisher eventPublisher;
86      private RememberMeServices rememberMeServices = new NullRememberMeServices();
87  
88      //~ Methods ================================================================
89  
90      public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) {
91          this.eventPublisher = eventPublisher;
92      }
93  
94      public void setRememberMeServices(RememberMeServices rememberMeServices) {
95          this.rememberMeServices = rememberMeServices;
96      }
97  
98      public RememberMeServices getRememberMeServices() {
99          return rememberMeServices;
100     }
101 
102     public void afterPropertiesSet() throws Exception {
103         Assert.notNull(rememberMeServices);
104     }
105 
106     /***
107      * Does nothing - we rely on IoC lifecycle services instead.
108      */
109     public void destroy() {}
110 
111     public void doFilter(ServletRequest request, ServletResponse response,
112         FilterChain chain) throws IOException, ServletException {
113         if (!(request instanceof HttpServletRequest)) {
114             throw new ServletException("Can only process HttpServletRequest");
115         }
116 
117         if (!(response instanceof HttpServletResponse)) {
118             throw new ServletException("Can only process HttpServletResponse");
119         }
120 
121         HttpServletRequest httpRequest = (HttpServletRequest) request;
122         HttpServletResponse httpResponse = (HttpServletResponse) response;
123 
124         if (SecurityContextHolder.getContext().getAuthentication() == null) {
125             Authentication rememberMeAuth =
126                     rememberMeServices.autoLogin(httpRequest, httpResponse);
127 
128             if(rememberMeAuth != null) {
129                 SecurityContextHolder.getContext().setAuthentication(rememberMeAuth);
130 
131                 if (logger.isDebugEnabled()) {
132                     logger.debug(
133                         "SecurityContextHolder populated with remember-me token: '"
134                         + SecurityContextHolder.getContext().getAuthentication()
135                         + "'");
136                 }
137 
138                 // Fire event
139                 if (this.eventPublisher != null) {
140                     eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(
141                             SecurityContextHolder.getContext().getAuthentication(),
142                             this.getClass()));
143                 }
144             }
145         } else {
146             if (logger.isDebugEnabled()) {
147                 logger.debug(
148                     "SecurityContextHolder not populated with remember-me token, as it already contained: '"
149                     + SecurityContextHolder.getContext().getAuthentication()
150                     + "'");
151             }
152         }
153 
154         chain.doFilter(request, response);
155     }
156 
157     /***
158      * Does nothing - we rely on IoC lifecycle services instead.
159      *
160      * @param ignored not used
161      *
162      */
163     public void init(FilterConfig ignored) throws ServletException {}
164 }