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 }