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.captcha;
17  
18  import org.acegisecurity.ConfigAttribute;
19  import org.acegisecurity.ConfigAttributeDefinition;
20  import org.acegisecurity.context.SecurityContextHolder;
21  import org.acegisecurity.intercept.web.FilterInvocation;
22  import org.acegisecurity.securechannel.ChannelEntryPoint;
23  import org.acegisecurity.securechannel.ChannelProcessor;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  
28  import org.springframework.beans.factory.InitializingBean;
29  
30  import org.springframework.util.Assert;
31  
32  import java.io.IOException;
33  
34  import java.util.Iterator;
35  
36  import javax.servlet.ServletException;
37  
38  
39  /***
40   * <p>
41   * CaptchaChannel template : Ensures the user has enough human privileges by
42   * review of the {@link CaptchaSecurityContext} and using an abstract routine
43   * {@link #isContextValidConcerningHumanity(CaptchaSecurityContext)}
44   * (implemented by sub classes)
45   * </p>
46   * 
47   * <P>
48   * The component uses 2 main parameters for its configuration :
49   * 
50   * <ul>
51   * <li>
52   * a keyword to be mapped to urls in the {@link
53   * org.acegisecurity.securechannel.ChannelProcessingFilter} configuration<br>
54   * default value provided by sub classes.
55   * </li>
56   * <li>
57   * and a thresold : used by the routine {@link
58   * #isContextValidConcerningHumanity(CaptchaSecurityContext)} to evaluate
59   * whether the {@link CaptchaSecurityContext} is valid default value = 0
60   * </li>
61   * </ul>
62   * </p>
63   *
64   * @author marc antoine Garrigue
65   * @version $Id: CaptchaChannelProcessorTemplate.java,v 1.2 2005/11/17 00:55:49 benalex Exp $
66   */
67  public abstract class CaptchaChannelProcessorTemplate
68      implements ChannelProcessor, InitializingBean {
69      //~ Instance fields ========================================================
70  
71      protected Log logger = LogFactory.getLog(this.getClass());
72      private ChannelEntryPoint entryPoint;
73      private String keyword = null;
74      private int thresold = 0;
75  
76      //~ Methods ================================================================
77  
78      public void setEntryPoint(ChannelEntryPoint entryPoint) {
79          this.entryPoint = entryPoint;
80      }
81  
82      public ChannelEntryPoint getEntryPoint() {
83          return entryPoint;
84      }
85  
86      public void setKeyword(String keyword) {
87          this.keyword = keyword;
88      }
89  
90      public String getKeyword() {
91          return keyword;
92      }
93  
94      public void setThresold(int thresold) {
95          this.thresold = thresold;
96      }
97  
98      public int getThresold() {
99          return thresold;
100     }
101 
102     /***
103      * Verify if entryPoint and keyword are ok
104      *
105      * @throws Exception if not
106      */
107     public void afterPropertiesSet() throws Exception {
108         Assert.notNull(entryPoint, "entryPoint required");
109         Assert.hasLength(keyword, "keyword required");
110     }
111 
112     public void decide(FilterInvocation invocation,
113         ConfigAttributeDefinition config) throws IOException, ServletException {
114         if ((invocation == null) || (config == null)) {
115             throw new IllegalArgumentException("Nulls cannot be provided");
116         }
117 
118         CaptchaSecurityContext context = null;
119         context = (CaptchaSecurityContext) SecurityContextHolder.getContext();
120 
121         Iterator iter = config.getConfigAttributes();
122 
123         while (iter.hasNext()) {
124             ConfigAttribute attribute = (ConfigAttribute) iter.next();
125 
126             if (supports(attribute)) {
127                 logger.debug("supports this attribute : " + attribute);
128 
129                 if (!isContextValidConcerningHumanity(context)) {
130                     logger.debug(
131                         "context is not allowed to access ressource, redirect to captcha entry point");
132                     redirectToEntryPoint(invocation);
133                 } else {
134                     logger.debug(
135                         "has been successfully checked this keyword, increment request count");
136                     context.incrementHumanRestrictedRessoucesRequestsCount();
137                 }
138             } else {
139                 logger.debug("do not support this attribute");
140             }
141         }
142     }
143 
144     public boolean supports(ConfigAttribute attribute) {
145         if ((attribute != null) && (keyword.equals(attribute.getAttribute()))) {
146             return true;
147         } else {
148             return false;
149         }
150     }
151 
152     abstract boolean isContextValidConcerningHumanity(
153         CaptchaSecurityContext context);
154 
155     private void redirectToEntryPoint(FilterInvocation invocation)
156         throws IOException, ServletException {
157         if (logger.isDebugEnabled()) {
158             logger.debug("context is not valid : redirecting to entry point");
159         }
160 
161         entryPoint.commence(invocation.getRequest(), invocation.getResponse());
162     }
163 }