Coverage Report - org.acegisecurity.providers.anonymous.AnonymousProcessingFilter
 
Classes in this File Line Coverage Branch Coverage Complexity
AnonymousProcessingFilter
87% 
100% 
1.385
 
 1  
 /* Copyright 2004, 2005, 2006 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.providers.anonymous;
 17  
 
 18  
 import org.acegisecurity.Authentication;
 19  
 
 20  
 import org.acegisecurity.context.SecurityContextHolder;
 21  
 
 22  
 import org.acegisecurity.ui.AuthenticationDetailsSource;
 23  
 import org.acegisecurity.ui.AuthenticationDetailsSourceImpl;
 24  
 
 25  
 import org.acegisecurity.userdetails.memory.UserAttribute;
 26  
 
 27  
 import org.apache.commons.logging.Log;
 28  
 import org.apache.commons.logging.LogFactory;
 29  
 
 30  
 import org.springframework.beans.factory.InitializingBean;
 31  
 
 32  
 import org.springframework.util.Assert;
 33  
 
 34  
 import java.io.IOException;
 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  
 import javax.servlet.http.HttpServletRequest;
 43  
 
 44  
 
 45  
 /**
 46  
  * Detects if there is no <code>Authentication</code> object in the <code>SecurityContextHolder</code>,  and
 47  
  * populates it with one if needed.<p><b>Do not use this class directly.</b> Instead configure <code>web.xml</code>
 48  
  * to use the {@link org.acegisecurity.util.FilterToBeanProxy}.</p>
 49  
  *
 50  
  * @author Ben Alex
 51  
  * @version $Id: AnonymousProcessingFilter.java 1496 2006-05-23 13:38:33Z benalex $
 52  
  */
 53  5
 public class AnonymousProcessingFilter implements Filter, InitializingBean {
 54  
     //~ Static fields/initializers =====================================================================================
 55  
 
 56  3
     private static final Log logger = LogFactory.getLog(AnonymousProcessingFilter.class);
 57  
 
 58  
     //~ Instance fields ================================================================================================
 59  
 
 60  5
     private AuthenticationDetailsSource authenticationDetailsSource = new AuthenticationDetailsSourceImpl();
 61  
     private String key;
 62  
     private UserAttribute userAttribute;
 63  5
     private boolean removeAfterRequest = true;
 64  
 
 65  
     //~ Methods ========================================================================================================
 66  
 
 67  
     public void afterPropertiesSet() throws Exception {
 68  5
         Assert.notNull(userAttribute);
 69  4
         Assert.hasLength(key);
 70  3
     }
 71  
 
 72  
     /**
 73  
      * Enables subclasses to determine whether or not an anonymous authentication token should be setup for
 74  
      * this request. This is useful if anonymous authentication should be allowed only for specific IP subnet ranges
 75  
      * etc.
 76  
      *
 77  
      * @param request to assist the method determine request details
 78  
      *
 79  
      * @return <code>true</code> if the anonymous token should be setup for this request (provided that the request
 80  
      *         doesn't already have some other <code>Authentication</code> inside it), or <code>false</code> if no
 81  
      *         anonymous token should be setup for this request
 82  
      */
 83  
     protected boolean applyAnonymousForThisRequest(ServletRequest request) {
 84  3
         return true;
 85  
     }
 86  
 
 87  
     protected Authentication createAuthentication(ServletRequest request) {
 88  3
         Assert.isInstanceOf(HttpServletRequest.class, request,
 89  
             "ServletRequest must be an instance of HttpServletRequest");
 90  
 
 91  3
         AnonymousAuthenticationToken auth = new AnonymousAuthenticationToken(key, userAttribute.getPassword(),
 92  
                 userAttribute.getAuthorities());
 93  3
         auth.setDetails(authenticationDetailsSource.buildDetails((HttpServletRequest) request));
 94  
 
 95  3
         return auth;
 96  
     }
 97  
 
 98  
     /**
 99  
      * Does nothing - we reply on IoC lifecycle services instead.
 100  
      */
 101  3
     public void destroy() {}
 102  
 
 103  
     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
 104  
         throws IOException, ServletException {
 105  3
         boolean addedToken = false;
 106  
 
 107  3
         if (applyAnonymousForThisRequest(request)) {
 108  3
             if (SecurityContextHolder.getContext().getAuthentication() == null) {
 109  2
                 SecurityContextHolder.getContext().setAuthentication(createAuthentication(request));
 110  2
                 addedToken = true;
 111  
 
 112  2
                 if (logger.isDebugEnabled()) {
 113  0
                     logger.debug("Populated SecurityContextHolder with anonymous token: '"
 114  
                         + SecurityContextHolder.getContext().getAuthentication() + "'");
 115  
                 }
 116  
             } else {
 117  1
                 if (logger.isDebugEnabled()) {
 118  0
                     logger.debug("SecurityContextHolder not populated with anonymous token, as it already contained: '"
 119  
                         + SecurityContextHolder.getContext().getAuthentication() + "'");
 120  
                 }
 121  
             }
 122  
         }
 123  
 
 124  
         try {
 125  3
             chain.doFilter(request, response);
 126  
         } finally {
 127  3
             if (addedToken && removeAfterRequest
 128  
                 && createAuthentication(request).equals(SecurityContextHolder.getContext().getAuthentication())) {
 129  1
                 SecurityContextHolder.getContext().setAuthentication(null);
 130  
             }
 131  
         }
 132  3
     }
 133  
 
 134  
     public String getKey() {
 135  1
         return key;
 136  
     }
 137  
 
 138  
     public UserAttribute getUserAttribute() {
 139  1
         return userAttribute;
 140  
     }
 141  
 
 142  
     /**
 143  
      * Does nothing - we reply on IoC lifecycle services instead.
 144  
      *
 145  
      * @param ignored not used
 146  
      *
 147  
      * @throws ServletException DOCUMENT ME!
 148  
      */
 149  3
     public void init(FilterConfig ignored) throws ServletException {}
 150  
 
 151  
     public boolean isRemoveAfterRequest() {
 152  2
         return removeAfterRequest;
 153  
     }
 154  
 
 155  
     public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
 156  0
         Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required");
 157  0
         this.authenticationDetailsSource = authenticationDetailsSource;
 158  0
     }
 159  
 
 160  
     public void setKey(String key) {
 161  4
         this.key = key;
 162  4
     }
 163  
 
 164  
     /**
 165  
      * Controls whether the filter will remove the Anonymous token after the request is complete. Generally
 166  
      * this is desired to avoid the expense of a session being created by {@link
 167  
      * org.acegisecurity.context.HttpSessionContextIntegrationFilter HttpSessionContextIntegrationFilter} simply to
 168  
      * store the Anonymous authentication token.<p>Defaults to <code>true</code>, being the most optimal and
 169  
      * appropriate option (ie <code>AnonymousProcessingFilter</code> will clear the token at the end of each request,
 170  
      * thus avoiding the session creation overhead in a typical configuration.</p>
 171  
      *
 172  
      * @param removeAfterRequest DOCUMENT ME!
 173  
      */
 174  
     public void setRemoveAfterRequest(boolean removeAfterRequest) {
 175  3
         this.removeAfterRequest = removeAfterRequest;
 176  3
     }
 177  
 
 178  
     public void setUserAttribute(UserAttribute userAttributeDefinition) {
 179  4
         this.userAttribute = userAttributeDefinition;
 180  4
     }
 181  
 }