diff --git a/core/src/main/java/org/acegisecurity/captcha/AlwaysTestAfterMaxRequestsCaptchaChannelProcessor.java b/core/src/main/java/org/acegisecurity/captcha/AlwaysTestAfterMaxRequestsCaptchaChannelProcessor.java
new file mode 100644
index 0000000000..63f9b3ed13
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/captcha/AlwaysTestAfterMaxRequestsCaptchaChannelProcessor.java
@@ -0,0 +1,68 @@
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Copyright (c) 2005 Your Corporation. All Rights Reserved.
+ */
+package net.sf.acegisecurity.captcha;
+
+/**
+ *
+ * return false if ny CaptchaChannelProcessorTemplate of mapped urls has been
+ * requested more than thresold;
+ * Default keyword : REQUIRES_CAPTCHA_ABOVE_THRESOLD_REQUESTS
+ *
+ *
+ * @author Marc-Antoine Garrigue
+ * @version $Id$
+ */
+public class AlwaysTestAfterMaxRequestsCaptchaChannelProcessor
+ extends CaptchaChannelProcessorTemplate {
+ //~ Static fields/initializers =============================================
+
+ /** Keyword for this channelProcessor */
+ public static final String DEFAULT_KEYWORD = "REQUIRES_CAPTCHA_ABOVE_THRESOLD_REQUESTS";
+
+ //~ Constructors ===========================================================
+
+ /**
+ * Constructor
+ */
+ public AlwaysTestAfterMaxRequestsCaptchaChannelProcessor() {
+ super();
+ this.setKeyword(DEFAULT_KEYWORD);
+ }
+
+ //~ Methods ================================================================
+
+ /**
+ * Verify wheter the context is valid concerning humanity
+ *
+ * @param context
+ *
+ * @return true if valid, false otherwise
+ */
+ boolean isContextValidConcerningHumanity(CaptchaSecurityContext context) {
+ if (context.getHumanRestrictedResourcesRequestsCount() < getThresold()) {
+ logger.debug("context is valid : request count < thresold");
+
+ return true;
+ } else {
+ logger.debug("context is not valid : request count > thresold");
+
+ return false;
+ }
+ }
+}
diff --git a/core/src/main/java/org/acegisecurity/captcha/AlwaysTestAfterTimeInMillisCaptchaChannelProcessor.java b/core/src/main/java/org/acegisecurity/captcha/AlwaysTestAfterTimeInMillisCaptchaChannelProcessor.java
new file mode 100644
index 0000000000..208fe0ae83
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/captcha/AlwaysTestAfterTimeInMillisCaptchaChannelProcessor.java
@@ -0,0 +1,66 @@
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.acegisecurity.captcha;
+
+/**
+ *
+ * return false if thresold is greater than millis since last captcha test has occured;
+ * Default keyword : REQUIRES_CAPTCHA_AFTER_THRESOLD_IN_MILLIS
+ *
+ *
+ * @author Marc-Antoine Garrigue
+ * @version $Id$
+ */
+public class AlwaysTestAfterTimeInMillisCaptchaChannelProcessor
+ extends CaptchaChannelProcessorTemplate {
+ //~ Static fields/initializers =============================================
+
+ /** Keyword for this channelProcessor */
+ public static final String DEFAULT_KEYWORD = "REQUIRES_CAPTCHA_AFTER_THRESOLD_IN_MILLIS";
+
+ //~ Constructors ===========================================================
+
+ /**
+ * Constructor
+ */
+ public AlwaysTestAfterTimeInMillisCaptchaChannelProcessor() {
+ super();
+ this.setKeyword(DEFAULT_KEYWORD);
+ }
+
+ //~ Methods ================================================================
+
+ /**
+ * Verify wheter the context is valid concerning humanity
+ *
+ * @param context the CaptchaSecurityContext
+ *
+ * @return true if valid, false otherwise
+ */
+ boolean isContextValidConcerningHumanity(CaptchaSecurityContext context) {
+ if ((System.currentTimeMillis()
+ - context.getLastPassedCaptchaDateInMillis()) < getThresold()) {
+ logger.debug(
+ "context is valid : last passed captcha date - current time < thresold");
+
+ return true;
+ } else {
+ logger.debug(
+ "context is not valid : last passed captcha date - current time > thresold");
+
+ return false;
+ }
+ }
+}
diff --git a/core/src/main/java/org/acegisecurity/captcha/AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor.java b/core/src/main/java/org/acegisecurity/captcha/AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor.java
new file mode 100644
index 0000000000..6ef02114ac
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/captcha/AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor.java
@@ -0,0 +1,93 @@
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.sf.acegisecurity.captcha;
+
+import org.springframework.util.Assert;
+
+
+/**
+ *
+ * return false if thresold is lower than average time millis between any
+ * CaptchaChannelProcessorTemplate mapped urls requests and is human;
+ * Default keyword : REQUIRES_CAPTCHA_AFTER_THRESOLD_IN_MILLIS
+ * Note : before first humanity check
+ *
+ *
+ * @author Marc-Antoine Garrigue
+ * @version $Id$
+ */
+public class AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor
+ extends CaptchaChannelProcessorTemplate {
+ //~ Static fields/initializers =============================================
+
+ /** Keyword for this channelProcessor */
+ public static final String DEFAULT_KEYWORD = "REQUIRES_CAPTCHA_BELOW_AVERAGE_TIME_IN_MILLIS_REQUESTS";
+
+ //~ Constructors ===========================================================
+
+ /**
+ * Constructor
+ */
+ public AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor() {
+ super();
+ this.setKeyword(DEFAULT_KEYWORD);
+ }
+
+ //~ Methods ================================================================
+
+ /**
+ * Verify if thresold is > 0
+ *
+ * @throws Exception if false
+ */
+ public void afterPropertiesSet() throws Exception {
+ super.afterPropertiesSet();
+ Assert.isTrue(getThresold() > 0, "thresold must be > 0");
+ }
+
+ /**
+ * Verify wheter the context is valid concerning humanity
+ *
+ * @param context
+ *
+ * @return true if valid, false otherwise
+ */
+ boolean isContextValidConcerningHumanity(CaptchaSecurityContext context) {
+ int req = context.getHumanRestrictedResourcesRequestsCount();
+ float thresold = getThresold();
+ float duration = System.currentTimeMillis()
+ - context.getLastPassedCaptchaDateInMillis();
+ float average;
+
+ if (req == 0) {
+ average = thresold + 1;
+ } else {
+ average = duration / req;
+ }
+
+ if (context.isHuman() && (average > thresold)) {
+ logger.debug(
+ "context is valid : average time between requests < thresold && is human");
+
+ return true;
+ } else {
+ logger.debug(
+ "context is not valid : request count > thresold or is not human");
+
+ return false;
+ }
+ }
+}
diff --git a/core/src/main/java/org/acegisecurity/captcha/CaptchaChannelProcessor.java b/core/src/main/java/org/acegisecurity/captcha/CaptchaChannelProcessor.java
deleted file mode 100644
index 87cebfce13..0000000000
--- a/core/src/main/java/org/acegisecurity/captcha/CaptchaChannelProcessor.java
+++ /dev/null
@@ -1,371 +0,0 @@
-/* Copyright 2004 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package net.sf.acegisecurity.captcha;
-
-import java.io.IOException;
-import java.util.Iterator;
-
-import javax.servlet.ServletException;
-
-import net.sf.acegisecurity.ConfigAttribute;
-import net.sf.acegisecurity.ConfigAttributeDefinition;
-import net.sf.acegisecurity.context.SecurityContextHolder;
-import net.sf.acegisecurity.intercept.web.FilterInvocation;
-import net.sf.acegisecurity.securechannel.ChannelEntryPoint;
-import net.sf.acegisecurity.securechannel.ChannelProcessor;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.util.Assert;
-
-/**
- *
- * Ensures the user has enougth human privileges by review of the
- * {@link net.sf.acegisecurity.captcha.CaptchaSecurityContext}.
- *
- *
- *
- * The class takes 3 required attributes :
- *
- * - maxRequestsBeforeFirstTest : used by
- * {@link #getRequiresHumanAfterMaxRequestsKeyword()} and
- * {@link #getRequiresHumanAfterMaxMillisKeyword()}
- * default value = 0 (ie first request).
- * - maxRequestsBeforeReTest : used by
- * {@link #getRequiresHumanAfterMaxMillisKeyword()}
- * default value = -1 (ie disabled, once in a {@link CaptchaSecurityContext}'s
- * life).
- * - maxMillisBeforeReTest: used by
- * {@link #getRequiresHumanAfterMaxMillisKeyword()}
- * default value = -1 (ie disabled, once in a {@link CaptchaSecurityContext}'s
- * life).
- *
- * The class responds to two case-sensitive keywords :
- *
- * - {@link #getRequiresHumanAfterMaxRequestsKeyword()}
- * default value = REQUIRES_HUMAN_AFTER_MAX_REQUESTS
- * if detected, checks if :
- *
- *
- * {@link CaptchaSecurityContext#isHuman()} == true
- * - or
- * {@link CaptchaSecurityContext#getHumanRestrictedResourcesRequestsCount()} < maxRequestsBeforeFirstTest
- *
- * - and
- *
- * {@link CaptchaSecurityContext#getHumanRestrictedResourcesRequestsCount()} < maxRequestsBeforeReTest
- * - or
- * maxRequestsBeforeReTest < 0
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- * - {@link #getRequiresHumanAfterMaxRequestsKeyword()}
- * default value = REQUIRES_HUMAN_AFTER_MAX_MILLIS
- * if detected, checks if :
- *
- *
- *
- * {@link CaptchaSecurityContext#isHuman()} == true
- * - or
- * {@link CaptchaSecurityContext#getHumanRestrictedResourcesRequestsCount()} < =maxRequestsBeforeFirstTest
- *
- * - and
- *
- * System.currentTimeMillis()-{@link CaptchaSecurityContext#getLastPassedCaptchaDateInMillis()} <= maxMillisBeforeReTest
- * - or
- * maxMillisBeforeReTest < 0
- *
- *
- *
- *
- *
- *
- *
- * Examples : to ensure an url is accessed only by human that pass a captcha
- * (assuming you are using the
- * {@link net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter})
- *
- *
- * - Once in a session and at first request : use the
- * REQUIRES_HUMAN_AFTER_MAX_REQUESTS keyword
- * with a maxRequestsBeforeFirstTest=0
- * and a maxRequestsBeforeReTest=-1
- *
- *
- *
- * - Once in a session and only after 3 requests : use the
- * REQUIRES_HUMAN_AFTER_MAX_REQUESTS keyword
- * with a maxRequestsBeforeFirstTest=3
- * and a maxRequestsBeforeReTest=-1
- *
- *
- * - Every request and only after 5 requests : use the
- * REQUIRES_HUMAN_AFTER_MAX_REQUESTS
- * with a maxRequestsBeforeReTest=0
- * and a maxRequestsBeforeFirstTest=5
- *
- *
- * - Every 3 requests and every minute : use the
- * REQUIRES_HUMAN_AFTER_MAX_MILLIS keywords
- * with a maxMillisBeforeReTest=6000
- * and a maxRequestsBeforeFirstTest=3
- *
- *
- * - Every 20 requests and every hour and only after 100 requests : use the
- *
- * REQUIRES_HUMAN_AFTER_MAX_REQUESTS
- * and the REQUIRES_HUMAN_AFTER_MAX_MILLIS
- * and the REQUIRES_HUMAN_AFTER_MAX_REQUESTS keywords
- * with a maxRequestsBeforeReTest=20
- * and a maxMillisBeforeReTest=3600000
- * and a maxRequestsBeforeFirstTest=1000
- *
- *
- *
- *
- * @author marc antoine Garrigue
- * @version $Id$
- */
-public class CaptchaChannelProcessor implements ChannelProcessor,
- InitializingBean {
- // ~ Static fields/initializers
- // =============================================
-
- private static final Log logger = LogFactory
- .getLog(CaptchaChannelProcessor.class);
-
- private String requiresHumanAfterMaxRequestsKeyword = "REQUIRES_HUMAN_AFTER_MAX_REQUESTS";
-
- private String requiresHumanAfterMaxMillisKeyword = "REQUIRES_HUMAN_AFTER_MAX_MILLIS";
-
- private String keywordPrefix = "";
-
-
- private ChannelEntryPoint entryPoint;
-
- private int maxRequestsBeforeReTest = -1;
-
- private int maxRequestsBeforeFirstTest = 0;
-
- private long maxMillisBeforeReTest = -1;
-
- public String getKeywordPrefix() {
- return keywordPrefix;
- }
-
- public void setKeywordPrefix(String keywordPrefix) {
- this.keywordPrefix = keywordPrefix;
- }
-
- public String getRequiresHumanAfterMaxMillisKeyword() {
- return requiresHumanAfterMaxMillisKeyword;
- }
-
- public void setRequiresHumanAfterMaxMillisKeyword(
- String requiresHumanAfterMaxMillis) {
- this.requiresHumanAfterMaxMillisKeyword = requiresHumanAfterMaxMillis;
-
- }
-
- public void setRequiresHumanAfterMaxRequestsKeyword(
- String requiresHumanAfterMaxRequestsKeyword) {
- this.requiresHumanAfterMaxRequestsKeyword = requiresHumanAfterMaxRequestsKeyword;
- }
-
- public ChannelEntryPoint getEntryPoint() {
- return entryPoint;
- }
-
- public void setEntryPoint(ChannelEntryPoint entryPoint) {
- this.entryPoint = entryPoint;
- }
-
- public int getMaxRequestsBeforeReTest() {
- return maxRequestsBeforeReTest;
- }
-
- public void setMaxRequestsBeforeReTest(int maxRequestsBeforeReTest) {
- this.maxRequestsBeforeReTest = maxRequestsBeforeReTest;
- }
-
- public String getRequiresHumanAfterMaxRequestsKeyword() {
- return requiresHumanAfterMaxRequestsKeyword;
- }
-
- public int getMaxRequestsBeforeFirstTest() {
- return maxRequestsBeforeFirstTest;
- }
-
- public void setMaxRequestsBeforeFirstTest(int maxRequestsBeforeFirstTest) {
- this.maxRequestsBeforeFirstTest = maxRequestsBeforeFirstTest;
- }
-
- public void afterPropertiesSet() throws Exception {
- Assert.notNull(entryPoint, "entryPoint required");
- }
-
- public long getMaxMillisBeforeReTest() {
- return maxMillisBeforeReTest;
- }
-
- public void setMaxMillisBeforeReTest(long maxMillisBeforeReTest) {
- this.maxMillisBeforeReTest = maxMillisBeforeReTest;
- }
-
- public void decide(FilterInvocation invocation,
- ConfigAttributeDefinition config) throws IOException,
- ServletException {
- if ((invocation == null) || (config == null)) {
- throw new IllegalArgumentException("Nulls cannot be provided");
- }
- CaptchaSecurityContext context = null;
- context = (CaptchaSecurityContext) SecurityContextHolder
- .getContext();
-
- Iterator iter = config.getConfigAttributes();
- boolean shouldRedirect = false;
-
- while (iter.hasNext()) {
- ConfigAttribute attribute = (ConfigAttribute) iter.next();
- if (supports(attribute)) {
- logger.debug("supports this attribute : " + attribute);
- if (!isContextValidForAttribute(context, attribute)) {
- shouldRedirect = true;
- }
- }
- }
- if (shouldRedirect) {
- logger
- .debug("context is not allowed to access ressource, redirect to captcha entry point");
- redirectToEntryPoint(invocation);
- } else {
- // if we reach this point, we forward the request so
- // increment it
- logger
- .debug("context is allowed to access ressource, increment rectricted ressource requests count ");
- context.incrementHumanRestrictedRessoucesRequestsCount();
-
- }
- }
-
- private boolean isContextValidForAttribute(CaptchaSecurityContext context,
- ConfigAttribute attribute) {
- boolean valid = false;
- if ((attribute != null) || (attribute.getAttribute() != null)) {
-
- // test the REQUIRES_HUMAN_AFTER_MAX_REQUESTS keyword
- if (isKeywordMaxRequest(attribute)) {
- if (isContextValidConcerningHumanOrFirstTest(context)
- && isContextValidConcerningReTest(context)) {
- valid = true;
- }
- }
-
- // test the REQUIRES_HUMAN_AFTER_MAX_MILLIS keyword
- if (isKeywordMillis(attribute)) {
- if (isContextValidConcerningHumanOrFirstTest(context)
- && isContextValidConcerningMaxMillis(context)) {
- valid = true;
- }
- }
-
- }
- return valid;
- }
-
- private boolean isContextValidConcerningHumanOrFirstTest(
- CaptchaSecurityContext context) {
- if (context.isHuman()
- || context.getHumanRestrictedResourcesRequestsCount() < maxRequestsBeforeFirstTest) {
- logger
- .debug("context is valid concerning humanity or request count < maxRequestsBeforeFirstTest");
-
- return true;
- } else {
- logger
- .debug("context is not valid concerning humanity and request count > maxRequestsBeforeFirstTest");
- return false;
- }
- }
-
- private boolean isContextValidConcerningReTest(
- CaptchaSecurityContext context) {
- if (context.getHumanRestrictedResourcesRequestsCount() < maxRequestsBeforeReTest
- || maxRequestsBeforeReTest < 0) {
- logger.debug("context is valid concerning reTest");
-
- return true;
- } else {
- logger.debug("context is not valid concerning reTest");
-
- return false;
- }
- }
-
- private boolean isContextValidConcerningMaxMillis(
- CaptchaSecurityContext context) {
- if (System.currentTimeMillis()
- - context.getLastPassedCaptchaDateInMillis() < maxMillisBeforeReTest
- || maxMillisBeforeReTest < 0) {
- logger.debug("context is valid concerning maxMillis");
-
- return true;
- } else {
- logger.debug("context is not valid concerning maxMillis");
-
- return false;
- }
- }
-
- private void redirectToEntryPoint(FilterInvocation invocation)
- throws IOException, ServletException {
- logger
- .debug("security constraints not repected : redirecting to entry point");
- entryPoint.commence(invocation.getRequest(), invocation.getResponse());
- return;
- }
-
- public boolean supports(ConfigAttribute attribute) {
- if ((attribute != null)
- && (attribute.getAttribute() != null)
- && (isKeywordMaxRequest(attribute) || isKeywordMillis(attribute)
-
- )) {
- return true;
- } else {
- return false;
- }
- }
-
- private boolean isKeywordMillis(ConfigAttribute attribute) {
- return attribute
- .getAttribute().equals(
- getKeywordPrefix()+getRequiresHumanAfterMaxMillisKeyword());
- }
-
- private boolean isKeywordMaxRequest(ConfigAttribute attribute) {
- return attribute.getAttribute().equals(
- getKeywordPrefix()+getRequiresHumanAfterMaxRequestsKeyword());
- }
-
-}
diff --git a/core/src/main/java/org/acegisecurity/captcha/CaptchaChannelProcessorTemplate.java b/core/src/main/java/org/acegisecurity/captcha/CaptchaChannelProcessorTemplate.java
new file mode 100644
index 0000000000..1e7f5e9f82
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/captcha/CaptchaChannelProcessorTemplate.java
@@ -0,0 +1,163 @@
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.sf.acegisecurity.captcha;
+
+import net.sf.acegisecurity.ConfigAttribute;
+import net.sf.acegisecurity.ConfigAttributeDefinition;
+import net.sf.acegisecurity.context.SecurityContextHolder;
+import net.sf.acegisecurity.intercept.web.FilterInvocation;
+import net.sf.acegisecurity.securechannel.ChannelEntryPoint;
+import net.sf.acegisecurity.securechannel.ChannelProcessor;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.beans.factory.InitializingBean;
+
+import org.springframework.util.Assert;
+
+import java.io.IOException;
+
+import java.util.Iterator;
+
+import javax.servlet.ServletException;
+
+
+/**
+ *
+ * CaptchaChannel template : Ensures the user has enough human privileges by
+ * review of the {@link CaptchaSecurityContext} and using an abstract routine
+ * {@link #isContextValidConcerningHumanity(CaptchaSecurityContext)}
+ * (implemented by sub classes)
+ *
+ *
+ *
+ * The component uses 2 main parameters for its configuration :
+ *
+ *
+ * -
+ * a keyword to be mapped to urls in the {@link
+ * net.sf.acegisecurity.securechannel.ChannelProcessingFilter} configuration
+ * default value provided by sub classes.
+ *
+ * -
+ * and a thresold : used by the routine {@link
+ * #isContextValidConcerningHumanity(CaptchaSecurityContext)} to evaluate
+ * whether the {@link CaptchaSecurityContext} is valid default value = 0
+ *
+ *
+ *
+ *
+ * @author marc antoine Garrigue
+ * @version $Id$
+ */
+public abstract class CaptchaChannelProcessorTemplate
+ implements ChannelProcessor, InitializingBean {
+ //~ Instance fields ========================================================
+
+ protected Log logger = LogFactory.getLog(this.getClass());
+ private ChannelEntryPoint entryPoint;
+ private String keyword = null;
+ private int thresold = 0;
+
+ //~ Methods ================================================================
+
+ public void setEntryPoint(ChannelEntryPoint entryPoint) {
+ this.entryPoint = entryPoint;
+ }
+
+ public ChannelEntryPoint getEntryPoint() {
+ return entryPoint;
+ }
+
+ public void setKeyword(String keyword) {
+ this.keyword = keyword;
+ }
+
+ public String getKeyword() {
+ return keyword;
+ }
+
+ public void setThresold(int thresold) {
+ this.thresold = thresold;
+ }
+
+ public int getThresold() {
+ return thresold;
+ }
+
+ /**
+ * Verify if entryPoint and keyword are ok
+ *
+ * @throws Exception if not
+ */
+ public void afterPropertiesSet() throws Exception {
+ Assert.notNull(entryPoint, "entryPoint required");
+ Assert.hasLength(keyword, "keyword required");
+ }
+
+ public void decide(FilterInvocation invocation,
+ ConfigAttributeDefinition config) throws IOException, ServletException {
+ if ((invocation == null) || (config == null)) {
+ throw new IllegalArgumentException("Nulls cannot be provided");
+ }
+
+ CaptchaSecurityContext context = null;
+ context = (CaptchaSecurityContext) SecurityContextHolder.getContext();
+
+ Iterator iter = config.getConfigAttributes();
+
+ while (iter.hasNext()) {
+ ConfigAttribute attribute = (ConfigAttribute) iter.next();
+
+ if (supports(attribute)) {
+ logger.debug("supports this attribute : " + attribute);
+
+ if (!isContextValidConcerningHumanity(context)) {
+ logger.debug(
+ "context is not allowed to access ressource, redirect to captcha entry point");
+ redirectToEntryPoint(invocation);
+ } else {
+ logger.debug(
+ "has been successfully checked this keyword, increment request count");
+ context.incrementHumanRestrictedRessoucesRequestsCount();
+ }
+ } else {
+ logger.debug("do not support this attribute");
+ }
+ }
+ }
+
+ public boolean supports(ConfigAttribute attribute) {
+ if ((attribute != null) && (keyword.equals(attribute.getAttribute()))) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ abstract boolean isContextValidConcerningHumanity(
+ CaptchaSecurityContext context);
+
+ private void redirectToEntryPoint(FilterInvocation invocation)
+ throws IOException, ServletException {
+ if (logger.isDebugEnabled()) {
+ logger.debug("context is not valid : redirecting to entry point");
+ }
+
+ entryPoint.commence(invocation.getRequest(), invocation.getResponse());
+ }
+}
diff --git a/core/src/main/java/org/acegisecurity/captcha/CaptchaEntryPoint.java b/core/src/main/java/org/acegisecurity/captcha/CaptchaEntryPoint.java
index 4f58d40f59..9e30b80a24 100644
--- a/core/src/main/java/org/acegisecurity/captcha/CaptchaEntryPoint.java
+++ b/core/src/main/java/org/acegisecurity/captcha/CaptchaEntryPoint.java
@@ -1,4 +1,4 @@
-/* Copyright 2004 Acegi Technology Pty Limited
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package net.sf.acegisecurity.captcha;
import net.sf.acegisecurity.securechannel.ChannelEntryPoint;
@@ -19,96 +20,142 @@ import net.sf.acegisecurity.util.PortMapper;
import net.sf.acegisecurity.util.PortMapperImpl;
import net.sf.acegisecurity.util.PortResolver;
import net.sf.acegisecurity.util.PortResolverImpl;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.springframework.beans.factory.InitializingBean;
+
import org.springframework.util.Assert;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+
+import java.net.URLEncoder;
+
+import java.util.Enumeration;
+
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.util.Enumeration;
+
/**
- * The captcha entry point : redirect to the captcha test page.
- *
- * This entry point can force the use of SSL : see {@link #getForceHttps()}
- *
- * This entry point allows internal OR external redirect : see {@link #setOutsideWebApp(boolean)}
/ Original request
- * can be added to the redirect path using a custom translation : see {@link #setIncludeOriginalRequest(boolean)}
- * Original request is translated using URLEncoding and the following translation mapping in the redirect url :
- * - original url => {@link #getOriginalRequestUrlParameterName()}
- If {@link
- * #isIncludeOriginalParameters()}
- original method => {@link #getOriginalRequestMethodParameterName()}
- * - original parameters => {@link #getOriginalRequestParametersParameterName()}
- The orinial parameters
- * string is contructed using :
- a parameter separator {@link #getOriginalRequestParametersSeparator()}
- *
- a parameter name value pair separator for each parameter {@link #getOriginalRequestParametersNameValueSeparator()}
- *
- *
- *
- *
- *
Default values :
forceHttps = false
includesOriginalRequest = true
includesOriginalParameters =
- * false
isOutsideWebApp=false
originalRequestUrlParameterName ="original_requestUrl"
- * originalRequestParametersParameterName = "original_request_parameters";
- *
- * originalRequestParametersNameValueSeparator = "@@";
- *
- * originalRequestParametersSeparator = ";;";
- *
- * originalRequestMethodParameterName = "original_request_method";
- *
- * urlEncodingCharset = "UTF-8";
+ * The captcha entry point : redirect to the captcha test page.
+ *
+ *
+ * This entry point can force the use of SSL : see {@link #getForceHttps()}
+ *
+ * This entry point allows internal OR external redirect : see {@link #setOutsideWebApp(boolean)}
+ * / Original request can be added to the redirect path using a custom
+ * translation : see {@link #setIncludeOriginalRequest(boolean)}
+ * Original request is translated using URLEncoding and the following
+ * translation mapping in the redirect url :
+ *
+ *
+ * -
+ * original url => {@link #getOriginalRequestUrlParameterName()}
+ *
+ * -
+ * If {@link #isIncludeOriginalParameters()}
+ *
+ * -
+ * original method => {@link #getOriginalRequestMethodParameterName()}
+ *
+ * -
+ * original parameters => {@link #getOriginalRequestParametersParameterName()}
+ *
+ * -
+ * The original parameters string is contructed using :
+ *
+ *
+ * -
+ * a parameter separator {@link #getOriginalRequestParametersSeparator()}
+ *
+ * -
+ * a parameter name value pair separator for each parameter {@link
+ * #getOriginalRequestParametersNameValueSeparator()}
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * Default values :
+ * forceHttps = false
+ * includesOriginalRequest = true
+ * includesOriginalParameters = false
+ * isOutsideWebApp=false
+ * originalRequestUrlParameterName =original_requestUrl
+ * originalRequestParametersParameterName = original_request_parameters
+ * originalRequestParametersNameValueSeparator = __
+ * originalRequestParametersSeparator = ;;
+ * originalRequestMethodParameterName = original_request_method
+ * urlEncodingCharset = UTF-8
*
* @author marc antoine Garrigue
* @version $Id$
*/
public class CaptchaEntryPoint implements ChannelEntryPoint, InitializingBean {
+ //~ Static fields/initializers =============================================
+
// ~ Static fields/initializers
// =============================================
+ private static final Log logger = LogFactory.getLog(CaptchaEntryPoint.class);
- private static final Log logger = LogFactory
- .getLog(CaptchaEntryPoint.class);
+ //~ Instance fields ========================================================
// ~ Instance fields
// ========================================================
-
private PortMapper portMapper = new PortMapperImpl();
-
private PortResolver portResolver = new PortResolverImpl();
-
private String captchaFormUrl;
-
- private boolean forceHttps = false;
-
- private String originalRequestUrlParameterName = "original_requestUrl";
-
- private String originalRequestParametersParameterName = "original_request_parameters";
-
- private String originalRequestParametersNameValueSeparator = "@@";
-
- private String originalRequestParametersSeparator = ";;";
-
private String originalRequestMethodParameterName = "original_request_method";
-
+ private String originalRequestParametersNameValueSeparator = "__";
+ private String originalRequestParametersParameterName = "original_request_parameters";
+ private String originalRequestParametersSeparator = ";;";
+ private String originalRequestUrlParameterName = "original_requestUrl";
private String urlEncodingCharset = "UTF-8";
-
+ private boolean forceHttps = false;
+ private boolean includeOriginalParameters = false;
+ private boolean includeOriginalRequest = true;
private boolean isOutsideWebApp = false;
- private boolean includeOriginalRequest = true;
+ //~ Methods ================================================================
- private boolean includeOriginalParameters = false;
+ /**
+ * The URL where the CaptchaProcessingFilter
login page can be
+ * found. Should be relative to the web-app context path, and include a
+ * leading /
+ *
+ * @param captchaFormUrl
+ */
+ public void setCaptchaFormUrl(String captchaFormUrl) {
+ this.captchaFormUrl = captchaFormUrl;
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @return the captcha test page to redirect to.
+ */
+ public String getCaptchaFormUrl() {
+ return captchaFormUrl;
+ }
// ~ Methods
// ================================================================
/**
- * Set to true to force captcha form access to be via https. If this value is ture (the default is false), and the
- * incoming request for the protected resource which triggered the interceptor was not already https
,
- * then
+ * Set to true to force captcha form access to be via https. If this value
+ * is ture (the default is false), and the incoming request for the
+ * protected resource which triggered the interceptor was not already
+ * https
, then
+ *
+ * @param forceHttps
*/
public void setForceHttps(boolean forceHttps) {
this.forceHttps = forceHttps;
@@ -118,19 +165,86 @@ public class CaptchaEntryPoint implements ChannelEntryPoint, InitializingBean {
return forceHttps;
}
- /**
- * The URL where the CaptchaProcessingFilter
login page can be found. Should be relative to the web-app
- * context path, and include a leading /
- */
- public void setCaptchaFormUrl(String captchaFormUrl) {
- this.captchaFormUrl = captchaFormUrl;
+ public void setIncludeOriginalParameters(boolean includeOriginalParameters) {
+ this.includeOriginalParameters = includeOriginalParameters;
+ }
+
+ public boolean isIncludeOriginalParameters() {
+ return includeOriginalParameters;
}
/**
- * @return the captcha test page to redirect to.
+ * If set to true, the original request url will be appended to the
+ * redirect url using the {@link #getOriginalRequestUrlParameterName()}.
+ *
+ * @param includeOriginalRequest
*/
- public String getCaptchaFormUrl() {
- return captchaFormUrl;
+ public void setIncludeOriginalRequest(boolean includeOriginalRequest) {
+ this.includeOriginalRequest = includeOriginalRequest;
+ }
+
+ public boolean isIncludeOriginalRequest() {
+ return includeOriginalRequest;
+ }
+
+ public void setOriginalRequestMethodParameterName(
+ String originalRequestMethodParameterName) {
+ this.originalRequestMethodParameterName = originalRequestMethodParameterName;
+ }
+
+ public String getOriginalRequestMethodParameterName() {
+ return originalRequestMethodParameterName;
+ }
+
+ public void setOriginalRequestParametersNameValueSeparator(
+ String originalRequestParametersNameValueSeparator) {
+ this.originalRequestParametersNameValueSeparator = originalRequestParametersNameValueSeparator;
+ }
+
+ public String getOriginalRequestParametersNameValueSeparator() {
+ return originalRequestParametersNameValueSeparator;
+ }
+
+ public void setOriginalRequestParametersParameterName(
+ String originalRequestParametersParameterName) {
+ this.originalRequestParametersParameterName = originalRequestParametersParameterName;
+ }
+
+ public String getOriginalRequestParametersParameterName() {
+ return originalRequestParametersParameterName;
+ }
+
+ public void setOriginalRequestParametersSeparator(
+ String originalRequestParametersSeparator) {
+ this.originalRequestParametersSeparator = originalRequestParametersSeparator;
+ }
+
+ public String getOriginalRequestParametersSeparator() {
+ return originalRequestParametersSeparator;
+ }
+
+ public void setOriginalRequestUrlParameterName(
+ String originalRequestUrlParameterName) {
+ this.originalRequestUrlParameterName = originalRequestUrlParameterName;
+ }
+
+ public String getOriginalRequestUrlParameterName() {
+ return originalRequestUrlParameterName;
+ }
+
+ /**
+ * if set to true, the {@link #commence(ServletRequest, ServletResponse)}
+ * method uses the {@link #getCaptchaFormUrl()} as a complete URL, else it
+ * as a 'inside WebApp' path.
+ *
+ * @param isOutsideWebApp
+ */
+ public void setOutsideWebApp(boolean isOutsideWebApp) {
+ this.isOutsideWebApp = isOutsideWebApp;
+ }
+
+ public boolean isOutsideWebApp() {
+ return isOutsideWebApp;
}
public void setPortMapper(PortMapper portMapper) {
@@ -149,104 +263,35 @@ public class CaptchaEntryPoint implements ChannelEntryPoint, InitializingBean {
return portResolver;
}
-
- public boolean isOutsideWebApp() {
- return isOutsideWebApp;
- }
-
-
- public String getOriginalRequestUrlParameterName() {
- return originalRequestUrlParameterName;
- }
-
- public void setOriginalRequestUrlParameterName(String originalRequestUrlParameterName) {
- this.originalRequestUrlParameterName = originalRequestUrlParameterName;
- }
-
- public String getOriginalRequestParametersParameterName() {
- return originalRequestParametersParameterName;
- }
-
- public void setOriginalRequestParametersParameterName(String originalRequestParametersParameterName) {
- this.originalRequestParametersParameterName = originalRequestParametersParameterName;
- }
-
- public String getOriginalRequestParametersNameValueSeparator() {
- return originalRequestParametersNameValueSeparator;
- }
-
- public void setOriginalRequestParametersNameValueSeparator(String originalRequestParametersNameValueSeparator) {
- this.originalRequestParametersNameValueSeparator = originalRequestParametersNameValueSeparator;
- }
-
- public String getOriginalRequestParametersSeparator() {
- return originalRequestParametersSeparator;
- }
-
- public void setOriginalRequestParametersSeparator(String originalRequestParametersSeparator) {
- this.originalRequestParametersSeparator = originalRequestParametersSeparator;
- }
-
- public String getOriginalRequestMethodParameterName() {
- return originalRequestMethodParameterName;
- }
-
- public void setOriginalRequestMethodParameterName(String originalRequestMethodParameterName) {
- this.originalRequestMethodParameterName = originalRequestMethodParameterName;
+ public void setUrlEncodingCharset(String urlEncodingCharset) {
+ this.urlEncodingCharset = urlEncodingCharset;
}
public String getUrlEncodingCharset() {
return urlEncodingCharset;
}
- public void setUrlEncodingCharset(String urlEncodingCharset) {
- this.urlEncodingCharset = urlEncodingCharset;
- }
-
- /**
- * if set to true, the {@link #commence(ServletRequest, ServletResponse)} method uses the {@link
- * #getCaptchaFormUrl()} as a complete URL, else it as a 'inside WebApp' path.
- */
- public void setOutsideWebApp(boolean isOutsideWebApp) {
- this.isOutsideWebApp = isOutsideWebApp;
- }
-
-
- public boolean isIncludeOriginalRequest() {
- return includeOriginalRequest;
- }
-
- /**
- * If set to true, the original request url will be appended to the redirect url using the {@link
- * #getOriginalRequestParameterName()}.
- */
- public void setIncludeOriginalRequest(boolean includeOriginalRequest) {
- this.includeOriginalRequest = includeOriginalRequest;
- }
-
- public boolean isIncludeOriginalParameters() {
- return includeOriginalParameters;
- }
-
- public void setIncludeOriginalParameters(boolean includeOriginalParameters) {
- this.includeOriginalParameters = includeOriginalParameters;
- }
-
public void afterPropertiesSet() throws Exception {
Assert.hasLength(captchaFormUrl, "captchaFormUrl must be specified");
- Assert.hasLength(originalRequestMethodParameterName, "originalRequestMethodParameterName must be specified");
- Assert.hasLength(originalRequestParametersNameValueSeparator, "originalRequestParametersNameValueSeparator must be specified");
- Assert.hasLength(originalRequestParametersParameterName, "originalRequestParametersParameterName must be specified");
- Assert.hasLength(originalRequestParametersSeparator, "originalRequestParametersSeparator must be specified");
- Assert.hasLength(originalRequestUrlParameterName, "originalRequestUrlParameterName must be specified");
- Assert.hasLength(urlEncodingCharset, "urlEncodingCharset must be specified");
+ Assert.hasLength(originalRequestMethodParameterName,
+ "originalRequestMethodParameterName must be specified");
+ Assert.hasLength(originalRequestParametersNameValueSeparator,
+ "originalRequestParametersNameValueSeparator must be specified");
+ Assert.hasLength(originalRequestParametersParameterName,
+ "originalRequestParametersParameterName must be specified");
+ Assert.hasLength(originalRequestParametersSeparator,
+ "originalRequestParametersSeparator must be specified");
+ Assert.hasLength(originalRequestUrlParameterName,
+ "originalRequestUrlParameterName must be specified");
+ Assert.hasLength(urlEncodingCharset,
+ "urlEncodingCharset must be specified");
Assert.notNull(portMapper, "portMapper must be specified");
Assert.notNull(portResolver, "portResolver must be specified");
URLEncoder.encode(" fzaef é& à ", urlEncodingCharset);
}
public void commence(ServletRequest request, ServletResponse response)
- throws IOException, ServletException {
+ throws IOException, ServletException {
StringBuffer redirectUrl = new StringBuffer();
HttpServletRequest req = (HttpServletRequest) request;
@@ -259,70 +304,17 @@ public class CaptchaEntryPoint implements ChannelEntryPoint, InitializingBean {
if (includeOriginalRequest) {
includeOriginalRequest(redirectUrl, req);
}
+
// add post parameter? DONE!
if (logger.isDebugEnabled()) {
logger.debug("Redirecting to: " + redirectUrl);
}
- ((HttpServletResponse) response)
- .sendRedirect(redirectUrl.toString());
- }
-
- private void includeOriginalRequest(StringBuffer redirectUrl,
- HttpServletRequest req) {
- // add original request to the url
- if (redirectUrl.indexOf("?") >= 0) {
- redirectUrl.append("&");
- } else {
- redirectUrl.append("?");
- }
-
- redirectUrl.append(originalRequestUrlParameterName);
- redirectUrl.append("=");
- try {
- redirectUrl.append(URLEncoder.encode(req.getRequestURL().toString(), urlEncodingCharset));
- } catch (UnsupportedEncodingException e) {
- logger.warn(e);
- }
-
- //append method
- redirectUrl.append("&");
- redirectUrl.append(originalRequestMethodParameterName);
- redirectUrl.append("=");
- redirectUrl.append(req.getMethod());
- if (includeOriginalParameters) {
-
- // append query params
-
- redirectUrl.append("&");
- redirectUrl.append(originalRequestParametersParameterName);
- redirectUrl.append("=");
- StringBuffer qp = new StringBuffer();
- Enumeration parameters = req.getParameterNames();
- if (parameters != null && parameters.hasMoreElements()) {
- //qp.append("?");
- while (parameters.hasMoreElements()) {
- String name = parameters.nextElement().toString();
- String value = req.getParameter(name);
- qp.append(name);
- qp.append(originalRequestParametersNameValueSeparator);
- qp.append(value);
- if (parameters.hasMoreElements()) {
- qp.append(originalRequestParametersSeparator);
- }
- }
- }
- try {
- redirectUrl.append(URLEncoder.encode(qp.toString(), urlEncodingCharset));
- } catch (Exception e) {
- logger.warn(e);
- }
- }
-
+ ((HttpServletResponse) response).sendRedirect(redirectUrl.toString());
}
private void buildInternalRedirect(StringBuffer redirectUrl,
- HttpServletRequest req) {
+ HttpServletRequest req) {
// construct it
StringBuffer simpleRedirect = new StringBuffer();
@@ -331,9 +323,11 @@ public class CaptchaEntryPoint implements ChannelEntryPoint, InitializingBean {
int serverPort = portResolver.getServerPort(req);
String contextPath = req.getContextPath();
boolean includePort = true;
+
if ("http".equals(scheme.toLowerCase()) && (serverPort == 80)) {
includePort = false;
}
+
if ("https".equals(scheme.toLowerCase()) && (serverPort == 443)) {
includePort = false;
}
@@ -341,10 +335,12 @@ public class CaptchaEntryPoint implements ChannelEntryPoint, InitializingBean {
simpleRedirect.append(scheme);
simpleRedirect.append("://");
simpleRedirect.append(serverName);
+
if (includePort) {
simpleRedirect.append(":");
simpleRedirect.append(serverPort);
}
+
simpleRedirect.append(contextPath);
simpleRedirect.append(captchaFormUrl);
@@ -361,10 +357,12 @@ public class CaptchaEntryPoint implements ChannelEntryPoint, InitializingBean {
redirectUrl.append("https://");
redirectUrl.append(serverName);
+
if (includePort) {
redirectUrl.append(":");
redirectUrl.append(httpsPort);
}
+
redirectUrl.append(contextPath);
redirectUrl.append(captchaFormUrl);
} else {
@@ -375,4 +373,61 @@ public class CaptchaEntryPoint implements ChannelEntryPoint, InitializingBean {
}
}
+ private void includeOriginalRequest(StringBuffer redirectUrl,
+ HttpServletRequest req) {
+ // add original request to the url
+ if (redirectUrl.indexOf("?") >= 0) {
+ redirectUrl.append("&");
+ } else {
+ redirectUrl.append("?");
+ }
+
+ redirectUrl.append(originalRequestUrlParameterName);
+ redirectUrl.append("=");
+
+ try {
+ redirectUrl.append(URLEncoder.encode(req.getRequestURL().toString(),
+ urlEncodingCharset));
+ } catch (UnsupportedEncodingException e) {
+ logger.warn(e);
+ }
+
+ //append method
+ redirectUrl.append("&");
+ redirectUrl.append(originalRequestMethodParameterName);
+ redirectUrl.append("=");
+ redirectUrl.append(req.getMethod());
+
+ if (includeOriginalParameters) {
+ // append query params
+ redirectUrl.append("&");
+ redirectUrl.append(originalRequestParametersParameterName);
+ redirectUrl.append("=");
+
+ StringBuffer qp = new StringBuffer();
+ Enumeration parameters = req.getParameterNames();
+
+ if ((parameters != null) && parameters.hasMoreElements()) {
+ //qp.append("?");
+ while (parameters.hasMoreElements()) {
+ String name = parameters.nextElement().toString();
+ String value = req.getParameter(name);
+ qp.append(name);
+ qp.append(originalRequestParametersNameValueSeparator);
+ qp.append(value);
+
+ if (parameters.hasMoreElements()) {
+ qp.append(originalRequestParametersSeparator);
+ }
+ }
+ }
+
+ try {
+ redirectUrl.append(URLEncoder.encode(qp.toString(),
+ urlEncodingCharset));
+ } catch (Exception e) {
+ logger.warn(e);
+ }
+ }
+ }
}
diff --git a/core/src/main/java/org/acegisecurity/captcha/CaptchaSecurityContext.java b/core/src/main/java/org/acegisecurity/captcha/CaptchaSecurityContext.java
index 03d3bb423a..769f1ee7d6 100644
--- a/core/src/main/java/org/acegisecurity/captcha/CaptchaSecurityContext.java
+++ b/core/src/main/java/org/acegisecurity/captcha/CaptchaSecurityContext.java
@@ -12,42 +12,50 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package net.sf.acegisecurity.captcha;
import net.sf.acegisecurity.context.SecurityContext;
+
/**
* Interface that add humanity concerns to the SecurityContext
- *
+ *
* @author marc antoine garrigue
*/
public interface CaptchaSecurityContext extends SecurityContext {
+ //~ Methods ================================================================
- /**
- * @return true if the current user has already passed a captcha.
- */
- boolean isHuman();
+ /**
+ * set human attribute, should called after captcha validation.
+ */
+ void setHuman();
- /**
- * set human attribute, should called after captcha validation.
- */
- void setHuman();
+ /**
+ * DOCUMENT ME!
+ *
+ * @return true if the current user has already passed a captcha.
+ */
+ boolean isHuman();
- /**
- *
- * @return number of human restricted resources requests since the last
- * passed captcha.
- */
- int getHumanRestrictedResourcesRequestsCount();
+ /**
+ * DOCUMENT ME!
+ *
+ * @return number of human restricted resources requests since the last
+ * passed captcha.
+ */
+ int getHumanRestrictedResourcesRequestsCount();
- /**
- * @return the date of the last passed Captcha in millis, 0 if the user
- * never passed captcha.
- */
- long getLastPassedCaptchaDateInMillis();
+ /**
+ * DOCUMENT ME!
+ *
+ * @return the date of the last passed Captcha in millis, 0 if the user
+ * never passed captcha.
+ */
+ long getLastPassedCaptchaDateInMillis();
- /**
- * Method to increment the human Restricted Resrouces Requests Count;
- */
- void incrementHumanRestrictedRessoucesRequestsCount();
+ /**
+ * Method to increment the human Restricted Resrouces Requests Count;
+ */
+ void incrementHumanRestrictedRessoucesRequestsCount();
}
diff --git a/core/src/main/java/org/acegisecurity/captcha/CaptchaSecurityContextImpl.java b/core/src/main/java/org/acegisecurity/captcha/CaptchaSecurityContextImpl.java
index 112fbbd965..68dbbc0aac 100644
--- a/core/src/main/java/org/acegisecurity/captcha/CaptchaSecurityContextImpl.java
+++ b/core/src/main/java/org/acegisecurity/captcha/CaptchaSecurityContextImpl.java
@@ -1,4 +1,4 @@
-/* Copyright 2004 Acegi Technology Pty Limited
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,74 +12,79 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package net.sf.acegisecurity.captcha;
import net.sf.acegisecurity.context.SecurityContextImpl;
+
/**
+ * Default CaptchaSecurityContext implementation
+ *
* @author mag
- *
*/
-public class CaptchaSecurityContextImpl extends SecurityContextImpl implements
- CaptchaSecurityContext {
+public class CaptchaSecurityContextImpl extends SecurityContextImpl
+ implements CaptchaSecurityContext {
+ //~ Instance fields ========================================================
- private boolean human;
+ private boolean human;
+ private int humanRestrictedResourcesRequestsCount;
+ private long lastPassedCaptchaDate;
- private long lastPassedCaptchaDate;
+ //~ Constructors ===========================================================
- private int humanRestrictedResourcesRequestsCount;
+ /**
+ *
+ */
+ public CaptchaSecurityContextImpl() {
+ super();
+ human = false;
+ lastPassedCaptchaDate = 0;
+ humanRestrictedResourcesRequestsCount = 0;
+ }
- /**
- *
- */
- public CaptchaSecurityContextImpl() {
- super();
- human = false;
- lastPassedCaptchaDate = 0;
- humanRestrictedResourcesRequestsCount = 0;
- }
+ //~ Methods ================================================================
- /*
- * (non-Javadoc)
- *
- * @see net.sf.acegisecurity.context.CaptchaSecurityContext#isHuman()
- */
- public boolean isHuman() {
- return human;
- }
+ /**
+ * reset the lastPassedCaptchaDate and count.
+ */
+ public void setHuman() {
+ this.human = true;
+ this.lastPassedCaptchaDate = System.currentTimeMillis();
+ this.humanRestrictedResourcesRequestsCount = 0;
+ }
- /**
- * reset the lastPassedCaptchaDate and count.
- */
- public void setHuman() {
- this.human = true;
- this.lastPassedCaptchaDate = System.currentTimeMillis();
- this.humanRestrictedResourcesRequestsCount = 0;
- }
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.sf.acegisecurity.context.CaptchaSecurityContext#isHuman()
+ */
+ public boolean isHuman() {
+ return human;
+ }
- /*
- * (non-Javadoc)
- *
- * @see net.sf.acegisecurity.context.CaptchaSecurityContext#getHumanRestrictedResourcesRequestsCount()
- */
- public int getHumanRestrictedResourcesRequestsCount() {
- return humanRestrictedResourcesRequestsCount;
- }
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.sf.acegisecurity.context.CaptchaSecurityContext#getHumanRestrictedResourcesRequestsCount()
+ */
+ public int getHumanRestrictedResourcesRequestsCount() {
+ return humanRestrictedResourcesRequestsCount;
+ }
- /*
- * (non-Javadoc)
- *
- * @see net.sf.acegisecurity.context.CaptchaSecurityContext#getLastPassedCaptchaDateInMillis()
- */
- public long getLastPassedCaptchaDateInMillis() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.sf.acegisecurity.context.CaptchaSecurityContext#getLastPassedCaptchaDateInMillis()
+ */
+ public long getLastPassedCaptchaDateInMillis() {
+ return lastPassedCaptchaDate;
+ }
- return lastPassedCaptchaDate;
- }
-
- /**
- * Method to increment the human Restricted Resrouces Requests Count;
- */
- public void incrementHumanRestrictedRessoucesRequestsCount() {
- humanRestrictedResourcesRequestsCount++;
- };
+ /**
+ * Method to increment the human Restricted Resrouces Requests Count;
+ */
+ public void incrementHumanRestrictedRessoucesRequestsCount() {
+ humanRestrictedResourcesRequestsCount++;
+ }
}
diff --git a/core/src/main/java/org/acegisecurity/captcha/CaptchaServiceProxy.java b/core/src/main/java/org/acegisecurity/captcha/CaptchaServiceProxy.java
index 2c1057e3c2..3cbdc9a833 100644
--- a/core/src/main/java/org/acegisecurity/captcha/CaptchaServiceProxy.java
+++ b/core/src/main/java/org/acegisecurity/captcha/CaptchaServiceProxy.java
@@ -1,4 +1,4 @@
-/* Copyright 2004 Acegi Technology Pty Limited
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,18 +17,24 @@ package net.sf.acegisecurity.captcha;
import javax.servlet.ServletRequest;
+
/**
* Provide a common interface for captcha validation.
- *
+ *
* @author marc antoine Garrigue
* @version $Id$
*/
public interface CaptchaServiceProxy {
+ //~ Methods ================================================================
- /**
+ /**
+ * DOCUMENT ME!
+ *
* @param id the id token
* @param captchaResponse the user response
- * @return true if the response is validated by the back end captcha service.
- */
- boolean validateReponseForId(String id , Object captchaResponse);
+ *
+ * @return true if the response is validated by the back end captcha
+ * service.
+ */
+ boolean validateReponseForId(String id, Object captchaResponse);
}
diff --git a/core/src/main/java/org/acegisecurity/captcha/CaptchaValidationProcessingFilter.java b/core/src/main/java/org/acegisecurity/captcha/CaptchaValidationProcessingFilter.java
index a72fd46969..167eb39ab4 100644
--- a/core/src/main/java/org/acegisecurity/captcha/CaptchaValidationProcessingFilter.java
+++ b/core/src/main/java/org/acegisecurity/captcha/CaptchaValidationProcessingFilter.java
@@ -1,4 +1,4 @@
-/* Copyright 2004 Acegi Technology Pty Limited
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,87 +15,96 @@
package net.sf.acegisecurity.captcha;
-import net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter;
import net.sf.acegisecurity.context.SecurityContextHolder;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.springframework.beans.factory.InitializingBean;
+import java.io.IOException;
+
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
-import java.io.IOException;
+
/**
- * Filter for web integration of the {@link CaptchaServiceProxy}.
It basically intercept calls containing the
- * specific validation parameter, use the {@link CaptchaServiceProxy} to validate the request, and update the {@link
- * CaptchaSecurityContext} if the request passed the validation.
This Filter should be placed after the
- * ContextIntegration filter and before the {@link CaptchaChannelProcessor} filter in the filter stack in order to
- * update the {@link CaptchaSecurityContext} before the humanity verification routine occurs.
This filter
- * should only be used in conjunction with the {@link CaptchaSecurityContext}
+ * Filter for web integration of the {@link CaptchaServiceProxy}.
+ * It basically intercept calls containing the specific validation parameter,
+ * use the {@link CaptchaServiceProxy} to validate the request, and update the
+ * {@link CaptchaSecurityContext} if the request passed the validation.
+ * This Filter should be placed after the ContextIntegration filter and before
+ * the {@link CaptchaChannelProcessorTemplate} filter in the filter stack in
+ * order to update the {@link CaptchaSecurityContext} before the humanity
+ * verification routine occurs.
+ * This filter should only be used in conjunction with the {@link
+ * CaptchaSecurityContext}
*
* @author marc antoine Garrigue
* @version $Id$
*/
public class CaptchaValidationProcessingFilter implements InitializingBean,
- Filter {
+ Filter {
+ //~ Static fields/initializers =============================================
+
// ~ Static fields/initializers
// =============================================
- protected static final Log logger = LogFactory
- .getLog(CaptchaValidationProcessingFilter.class);
+ protected static final Log logger = LogFactory.getLog(CaptchaValidationProcessingFilter.class);
+
+ //~ Instance fields ========================================================
// ~ Instance fields
// ========================================================
-
private CaptchaServiceProxy captchaService;
private String captchaValidationParameter = "_captcha_parameter";
-
- // ~ Methods
- // ================================================================
-
- public CaptchaServiceProxy getCaptchaService() {
- return captchaService;
- }
+ //~ Methods ================================================================
public void setCaptchaService(CaptchaServiceProxy captchaService) {
this.captchaService = captchaService;
}
-
- public String getCaptchaValidationParameter() {
- return captchaValidationParameter;
+ // ~ Methods
+ // ================================================================
+ public CaptchaServiceProxy getCaptchaService() {
+ return captchaService;
}
public void setCaptchaValidationParameter(String captchaValidationParameter) {
this.captchaValidationParameter = captchaValidationParameter;
}
+ public String getCaptchaValidationParameter() {
+ return captchaValidationParameter;
+ }
+
public void afterPropertiesSet() throws Exception {
if (this.captchaService == null) {
throw new IllegalArgumentException(
- "CaptchaServiceProxy must be defined ");
+ "CaptchaServiceProxy must be defined ");
}
- if (this.captchaValidationParameter == null||"".equals(captchaValidationParameter)) {
+
+ if ((this.captchaValidationParameter == null)
+ || "".equals(captchaValidationParameter)) {
throw new IllegalArgumentException(
- "captchaValidationParameter must not be empty or null");
+ "captchaValidationParameter must not be empty or null");
}
}
/**
* Does nothing. We use IoC container lifecycle services instead.
*/
- public void destroy() {
- }
+ public void destroy() {}
public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException {
- String captcha_reponse = request
- .getParameter(captchaValidationParameter);
- if ((request != null) && request instanceof HttpServletRequest
- && ( captcha_reponse!= null)) {
+ FilterChain chain) throws IOException, ServletException {
+ String captcha_reponse = request.getParameter(captchaValidationParameter);
+ if ((request != null) && request instanceof HttpServletRequest
+ && (captcha_reponse != null)) {
logger.debug("captcha validation parameter found");
+
// validate the request against CaptchaServiceProxy
boolean valid = false;
@@ -103,30 +112,35 @@ public class CaptchaValidationProcessingFilter implements InitializingBean,
//get session
HttpSession session = ((HttpServletRequest) request).getSession();
- if (session != null) {
+ if (session != null) {
String id = session.getId();
valid = this.captchaService.validateReponseForId(id,
captcha_reponse);
logger.debug("captchaServiceProxy says : request is valid = "
- + valid);
+ + valid);
+
if (valid) {
logger.debug("update the context");
((CaptchaSecurityContext) SecurityContextHolder.getContext())
- .setHuman();
+ .setHuman();
+
//logger.debug("retrieve original request from ")
-
- }else{
- logger.debug("captcha test failed");
+ } else {
+ logger.debug("captcha test failed");
}
-
- }else{
- logger.debug("no session found, user don't even ask a captcha challenge");
+ } else {
+ logger.debug(
+ "no session found, user don't even ask a captcha challenge");
}
} else {
- logger.debug("captcha validation parameter not found, do nothing");
+ logger.debug("captcha validation parameter not found, do nothing");
}
- logger.debug("chain ...");
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("chain ...");
+ }
+
chain.doFilter(request, response);
}
@@ -137,6 +151,5 @@ public class CaptchaValidationProcessingFilter implements InitializingBean,
*
* @throws ServletException ignored
*/
- public void init(FilterConfig filterConfig) throws ServletException {
- }
+ public void init(FilterConfig filterConfig) throws ServletException {}
}
diff --git a/core/src/main/java/org/acegisecurity/captcha/TestOnceAfterMaxRequestsCaptchaChannelProcessor.java b/core/src/main/java/org/acegisecurity/captcha/TestOnceAfterMaxRequestsCaptchaChannelProcessor.java
new file mode 100644
index 0000000000..c9ff09624e
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/captcha/TestOnceAfterMaxRequestsCaptchaChannelProcessor.java
@@ -0,0 +1,56 @@
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.acegisecurity.captcha;
+
+/**
+ *
+ * return false if ny CaptchaChannelProcessorTemplate mapped urls has been
+ * requested more than thresold and humanity is false;
+ * Default keyword : REQUIRES_CAPTCHA_ONCE_ABOVE_THRESOLD_REQUESTS
+ *
+ *
+ * @author Marc-Antoine Garrigue
+ * @version $Id$
+ */
+public class TestOnceAfterMaxRequestsCaptchaChannelProcessor
+ extends CaptchaChannelProcessorTemplate {
+ //~ Static fields/initializers =============================================
+
+ public static final String DEFAULT_KEYWORD = "REQUIRES_CAPTCHA_ONCE_ABOVE_THRESOLD_REQUESTS";
+
+ //~ Constructors ===========================================================
+
+ public TestOnceAfterMaxRequestsCaptchaChannelProcessor() {
+ super();
+ this.setKeyword(DEFAULT_KEYWORD);
+ }
+
+ //~ Methods ================================================================
+
+ boolean isContextValidConcerningHumanity(CaptchaSecurityContext context) {
+ if (context.isHuman()
+ || (context.getHumanRestrictedResourcesRequestsCount() < getThresold())) {
+ logger.debug(
+ "context is valid concerning humanity or request count < thresold");
+
+ return true;
+ } else {
+ logger.debug(
+ "context is not valid concerning humanity and request count > thresold");
+
+ return false;
+ }
+ }
+}
diff --git a/core/src/main/java/org/acegisecurity/captcha/package.html b/core/src/main/java/org/acegisecurity/captcha/package.html
index 2786b1d912..8ae2702220 100644
--- a/core/src/main/java/org/acegisecurity/captcha/package.html
+++ b/core/src/main/java/org/acegisecurity/captcha/package.html
@@ -1,6 +1,12 @@
-Captcha classes.
+Captcha classes. Contains :
+
+ - a CaptchaSecurityContext that overrides the default SecurityContext and holds some captcha related informations
+ - an abstract CaptchaChannelProcessorTemplate and its implementations that test this context according to the configuration
+ - a CaptchaServiceProxy and a CaptchaValidationProcessingFilter that alows to validate a captcha response and to update the CaptchaSecurity
+ - a CaptchaEntryPoint that redirects to a captcha page if the CaptchaChannelProcessor implementation decide so
+
diff --git a/core/src/test/java/org/acegisecurity/captcha/AlwaysTestAfterMaxRequestsCaptchaChannelProcessorTests.java b/core/src/test/java/org/acegisecurity/captcha/AlwaysTestAfterMaxRequestsCaptchaChannelProcessorTests.java
new file mode 100644
index 0000000000..c48b667691
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/captcha/AlwaysTestAfterMaxRequestsCaptchaChannelProcessorTests.java
@@ -0,0 +1,76 @@
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.sf.acegisecurity.captcha;
+
+import junit.framework.*;
+
+import net.sf.acegisecurity.captcha.AlwaysTestAfterMaxRequestsCaptchaChannelProcessor;
+
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author $author$
+ * @version $Revision$
+ */
+public class AlwaysTestAfterMaxRequestsCaptchaChannelProcessorTests
+ extends TestCase {
+ //~ Instance fields ========================================================
+
+ AlwaysTestAfterMaxRequestsCaptchaChannelProcessor alwaysTestAfterMaxRequestsCaptchaChannelProcessor;
+
+ //~ Methods ================================================================
+
+ public void testIsContextValidConcerningHumanity()
+ throws Exception {
+ alwaysTestAfterMaxRequestsCaptchaChannelProcessor.setThresold(1);
+
+ CaptchaSecurityContextImpl context = new CaptchaSecurityContextImpl();
+ assertTrue(alwaysTestAfterMaxRequestsCaptchaChannelProcessor
+ .isContextValidConcerningHumanity(context));
+
+ context.incrementHumanRestrictedRessoucesRequestsCount();
+
+ alwaysTestAfterMaxRequestsCaptchaChannelProcessor.setThresold(-1);
+ assertFalse(alwaysTestAfterMaxRequestsCaptchaChannelProcessor
+ .isContextValidConcerningHumanity(context));
+
+ alwaysTestAfterMaxRequestsCaptchaChannelProcessor.setThresold(3);
+ assertTrue(alwaysTestAfterMaxRequestsCaptchaChannelProcessor
+ .isContextValidConcerningHumanity(context));
+ context.incrementHumanRestrictedRessoucesRequestsCount();
+ assertTrue(alwaysTestAfterMaxRequestsCaptchaChannelProcessor
+ .isContextValidConcerningHumanity(context));
+ context.incrementHumanRestrictedRessoucesRequestsCount();
+ assertFalse(alwaysTestAfterMaxRequestsCaptchaChannelProcessor
+ .isContextValidConcerningHumanity(context));
+ }
+
+ public void testNewContext() {
+ CaptchaSecurityContextImpl context = new CaptchaSecurityContextImpl();
+
+ assertFalse(alwaysTestAfterMaxRequestsCaptchaChannelProcessor
+ .isContextValidConcerningHumanity(context));
+ alwaysTestAfterMaxRequestsCaptchaChannelProcessor.setThresold(1);
+ assertTrue(alwaysTestAfterMaxRequestsCaptchaChannelProcessor
+ .isContextValidConcerningHumanity(context));
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ alwaysTestAfterMaxRequestsCaptchaChannelProcessor = new AlwaysTestAfterMaxRequestsCaptchaChannelProcessor();
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/captcha/AlwaysTestAfterTimeInMillisCaptchaChannelProcessorTests.java b/core/src/test/java/org/acegisecurity/captcha/AlwaysTestAfterTimeInMillisCaptchaChannelProcessorTests.java
new file mode 100644
index 0000000000..7e6ef6c781
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/captcha/AlwaysTestAfterTimeInMillisCaptchaChannelProcessorTests.java
@@ -0,0 +1,98 @@
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.sf.acegisecurity.captcha;
+
+import junit.framework.*;
+
+import net.sf.acegisecurity.captcha.AlwaysTestAfterTimeInMillisCaptchaChannelProcessor;
+
+
+/**
+ * WARNING! This test class make some assumptions concerning the compute speed!
+ * For example the two following instructions should be computed in the same
+ * millis or the test is not valid.
+ *
+ * context.setHuman();
+ * assertFalse(alwaysTestAfterTimeInMillisCaptchaChannelProcessor.isContextValidConcerningHumanity(context));
+ *
+ * This should be the case for most environements unless
+ *
+ *
+ * -
+ * you run it on a good old TRS-80
+ *
+ * -
+ * you start M$office during this test ;)
+ *
+ *
+ */
+public class AlwaysTestAfterTimeInMillisCaptchaChannelProcessorTests
+ extends TestCase {
+ //~ Instance fields ========================================================
+
+ AlwaysTestAfterTimeInMillisCaptchaChannelProcessor alwaysTestAfterTimeInMillisCaptchaChannelProcessor;
+
+ //~ Methods ================================================================
+
+ public void testEqualsThresold() {
+ CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
+ assertFalse(alwaysTestAfterTimeInMillisCaptchaChannelProcessor
+ .isContextValidConcerningHumanity(context));
+
+ //the two following instructions should be computed or the test is not valid (never fails). This should be the case
+ // for most environements unless if you run it on a good old TRS-80 (thanks mom).
+ context.setHuman();
+ assertFalse(alwaysTestAfterTimeInMillisCaptchaChannelProcessor
+ .isContextValidConcerningHumanity(context));
+ }
+
+ public void testIsContextValidConcerningHumanity()
+ throws Exception {
+ CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
+ alwaysTestAfterTimeInMillisCaptchaChannelProcessor.setThresold(100);
+ context.setHuman();
+
+ while ((System.currentTimeMillis()
+ - context.getLastPassedCaptchaDateInMillis()) < alwaysTestAfterTimeInMillisCaptchaChannelProcessor
+ .getThresold()) {
+ assertTrue(alwaysTestAfterTimeInMillisCaptchaChannelProcessor
+ .isContextValidConcerningHumanity(context));
+ context.incrementHumanRestrictedRessoucesRequestsCount();
+
+ long now = System.currentTimeMillis();
+
+ while ((System.currentTimeMillis() - now) < 1) {}
+
+ ;
+ }
+
+ assertFalse(alwaysTestAfterTimeInMillisCaptchaChannelProcessor
+ .isContextValidConcerningHumanity(context));
+ }
+
+ public void testNewContext() {
+ CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
+
+ //alwaysTestAfterTimeInMillisCaptchaChannelProcessor.setThresold(10);
+ assertFalse(alwaysTestAfterTimeInMillisCaptchaChannelProcessor
+ .isContextValidConcerningHumanity(context));
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ alwaysTestAfterTimeInMillisCaptchaChannelProcessor = new AlwaysTestAfterTimeInMillisCaptchaChannelProcessor();
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/captcha/AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessorTests.java b/core/src/test/java/org/acegisecurity/captcha/AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessorTests.java
new file mode 100644
index 0000000000..06cc40e61f
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/captcha/AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessorTests.java
@@ -0,0 +1,125 @@
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.sf.acegisecurity.captcha;
+
+import junit.framework.TestCase;
+
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author $author$
+ * @version $Revision$
+ */
+public class AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessorTests
+ extends TestCase {
+ //~ Instance fields ========================================================
+
+ AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor;
+
+ //~ Methods ================================================================
+
+ public void testEqualsThresold() {
+ CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
+ alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor
+ .setThresold(100);
+
+ context.setHuman();
+
+ long now = System.currentTimeMillis();
+
+ while ((System.currentTimeMillis() - now) <= 100) {
+ assertTrue(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor
+ .isContextValidConcerningHumanity(context));
+ }
+
+ context.incrementHumanRestrictedRessoucesRequestsCount();
+ assertTrue(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor
+ .isContextValidConcerningHumanity(context));
+
+ context.setHuman();
+ context.incrementHumanRestrictedRessoucesRequestsCount();
+ assertFalse(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor
+ .isContextValidConcerningHumanity(context));
+
+ alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor
+ .setThresold(0);
+ context.setHuman();
+ context.incrementHumanRestrictedRessoucesRequestsCount();
+ assertFalse(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor
+ .isContextValidConcerningHumanity(context));
+ alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor
+ .setThresold(0);
+ }
+
+ public void testIsContextValidConcerningHumanity()
+ throws Exception {
+ CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
+ alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor
+ .setThresold(10);
+ context.setHuman();
+
+ while ((System.currentTimeMillis()
+ - context.getLastPassedCaptchaDateInMillis()) < (10 * alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor
+ .getThresold())) {
+ assertTrue(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor
+ .isContextValidConcerningHumanity(context));
+ }
+ }
+
+ public void testNewContext() {
+ CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
+ assertFalse(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor
+ .isContextValidConcerningHumanity(context));
+
+ context.setHuman();
+ assertTrue(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor
+ .isContextValidConcerningHumanity(context));
+ }
+
+ public void testShouldPassAbove() {
+ CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
+
+ context.setHuman();
+
+ int i = 0;
+
+ while ((System.currentTimeMillis()
+ - context.getLastPassedCaptchaDateInMillis()) < (100 * alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor
+ .getThresold())) {
+ System.out.println((System.currentTimeMillis()
+ - context.getLastPassedCaptchaDateInMillis()));
+
+ context.incrementHumanRestrictedRessoucesRequestsCount();
+ i++;
+
+ while ((System.currentTimeMillis()
+ - context.getLastPassedCaptchaDateInMillis()) < (alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor
+ .getThresold() * i)) {}
+
+ System.out.println((System.currentTimeMillis()
+ - context.getLastPassedCaptchaDateInMillis()));
+
+ assertTrue(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor
+ .isContextValidConcerningHumanity(context));
+ }
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor = new AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor();
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/captcha/CaptchaChannelProcessorTemplateTests.java b/core/src/test/java/org/acegisecurity/captcha/CaptchaChannelProcessorTemplateTests.java
new file mode 100644
index 0000000000..5b570accbe
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/captcha/CaptchaChannelProcessorTemplateTests.java
@@ -0,0 +1,216 @@
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.acegisecurity.captcha;
+
+import junit.framework.TestCase;
+
+import net.sf.acegisecurity.ConfigAttributeDefinition;
+import net.sf.acegisecurity.MockFilterChain;
+import net.sf.acegisecurity.SecurityConfig;
+import net.sf.acegisecurity.context.SecurityContextHolder;
+import net.sf.acegisecurity.intercept.web.FilterInvocation;
+
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+
+
+/**
+ * Tests {@link net.sf.acegisecurity.captcha.CaptchaChannelProcessorTemplate}
+ *
+ * @author marc antoine Garrigue
+ * @version $Id$
+ */
+public class CaptchaChannelProcessorTemplateTests extends TestCase {
+ //~ Methods ================================================================
+
+ public void testContextRedirect() throws Exception {
+ CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor();
+ processor.setKeyword("X");
+
+ ConfigAttributeDefinition cad = new ConfigAttributeDefinition();
+ cad.addConfigAttribute(new SecurityConfig("Y"));
+
+ CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
+ SecurityContextHolder.setContext(context);
+
+ CaptchaEntryPoint epoint = new CaptchaEntryPoint();
+ epoint.setCaptchaFormUrl("/jcaptcha.do");
+ epoint.setIncludeOriginalRequest(false);
+
+ processor.setEntryPoint(epoint);
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setQueryString("info=true");
+ request.setServerName("localhost");
+ request.setContextPath("/demo");
+ request.setServletPath("/restricted");
+ request.setScheme("http");
+ request.setServerPort(8000);
+
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ MockFilterChain chain = new MockFilterChain();
+ FilterInvocation fi = new FilterInvocation(request, response, chain);
+
+ processor.decide(fi, cad);
+ assertEquals(null, response.getRedirectedUrl());
+ processor.setKeyword("Y");
+ response = decideWithNewResponse(cad, processor, request);
+ assertEquals("http://localhost:8000/demo/jcaptcha.do",
+ response.getRedirectedUrl());
+ context.setHuman();
+ response = decideWithNewResponse(cad, processor, request);
+ assertEquals(null, response.getRedirectedUrl());
+ }
+
+ public void testDecideRejectsNulls() throws Exception {
+ CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor();
+ processor.setEntryPoint(new CaptchaEntryPoint());
+ processor.setKeyword("X");
+ processor.afterPropertiesSet();
+
+ try {
+ processor.decide(null, null);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testGettersSetters() {
+ CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor();
+ assertEquals(null, processor.getKeyword());
+ processor.setKeyword("X");
+ assertEquals("X", processor.getKeyword());
+
+ assertEquals(0, processor.getThresold());
+ processor.setThresold(1);
+ assertEquals(1, processor.getThresold());
+
+ assertTrue(processor.getEntryPoint() == null);
+ processor.setEntryPoint(new CaptchaEntryPoint());
+ assertTrue(processor.getEntryPoint() != null);
+ }
+
+ public void testIncrementRequestCount() throws Exception {
+ CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor();
+ processor.setKeyword("X");
+
+ ConfigAttributeDefinition cad = new ConfigAttributeDefinition();
+ cad.addConfigAttribute(new SecurityConfig("X"));
+
+ CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
+ SecurityContextHolder.setContext(context);
+
+ CaptchaEntryPoint epoint = new CaptchaEntryPoint();
+ epoint.setCaptchaFormUrl("/jcaptcha.do");
+ processor.setEntryPoint(epoint);
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setQueryString("info=true");
+ request.setServerName("localhost");
+ request.setContextPath("/demo");
+ request.setServletPath("/restricted");
+ request.setScheme("http");
+ request.setServerPort(8000);
+
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ MockFilterChain chain = new MockFilterChain();
+ FilterInvocation fi = new FilterInvocation(request, response, chain);
+
+ processor.decide(fi, cad);
+ assertEquals(0, context.getHumanRestrictedResourcesRequestsCount());
+ context.setHuman();
+ decideWithNewResponse(cad, processor, request);
+ assertEquals(1, context.getHumanRestrictedResourcesRequestsCount());
+ decideWithNewResponse(cad, processor, request);
+ assertEquals(2, context.getHumanRestrictedResourcesRequestsCount());
+ processor.setKeyword("Y");
+ decideWithNewResponse(cad, processor, request);
+ assertEquals(2, context.getHumanRestrictedResourcesRequestsCount());
+ context = new CaptchaSecurityContextImpl();
+ decideWithNewResponse(cad, processor, request);
+ assertEquals(0, context.getHumanRestrictedResourcesRequestsCount());
+ }
+
+ public void testMissingEntryPoint() throws Exception {
+ CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor();
+ processor.setEntryPoint(null);
+
+ try {
+ processor.afterPropertiesSet();
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("entryPoint required", expected.getMessage());
+ }
+ }
+
+ public void testMissingKeyword() throws Exception {
+ CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor();
+ processor.setKeyword(null);
+
+ try {
+ processor.afterPropertiesSet();
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {}
+
+ processor.setKeyword("");
+
+ try {
+ processor.afterPropertiesSet();
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {}
+ }
+
+ public void testSupports() {
+ CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor();
+ processor.setKeyword("X");
+ assertTrue(processor.supports(
+ new SecurityConfig(processor.getKeyword())));
+
+ assertTrue(processor.supports(new SecurityConfig("X")));
+
+ assertFalse(processor.supports(null));
+
+ assertFalse(processor.supports(new SecurityConfig("NOT_SUPPORTED")));
+ }
+
+ private MockHttpServletResponse decideWithNewResponse(
+ ConfigAttributeDefinition cad,
+ CaptchaChannelProcessorTemplate processor,
+ MockHttpServletRequest request) throws IOException, ServletException {
+ MockHttpServletResponse response;
+ MockFilterChain chain;
+ FilterInvocation fi;
+ response = new MockHttpServletResponse();
+ chain = new MockFilterChain();
+ fi = new FilterInvocation(request, response, chain);
+ processor.decide(fi, cad);
+
+ return response;
+ }
+
+ //~ Inner Classes ==========================================================
+
+ private class TestHumanityCaptchaChannelProcessor
+ extends CaptchaChannelProcessorTemplate {
+ boolean isContextValidConcerningHumanity(CaptchaSecurityContext context) {
+ return context.isHuman();
+ }
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/captcha/CaptchaChannelProcessorTests.java b/core/src/test/java/org/acegisecurity/captcha/CaptchaChannelProcessorTests.java
deleted file mode 100644
index 65f3aa3b01..0000000000
--- a/core/src/test/java/org/acegisecurity/captcha/CaptchaChannelProcessorTests.java
+++ /dev/null
@@ -1,552 +0,0 @@
-/* Copyright 2004 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.sf.acegisecurity.captcha;
-
-import junit.framework.TestCase;
-import net.sf.acegisecurity.ConfigAttributeDefinition;
-import net.sf.acegisecurity.MockFilterChain;
-import net.sf.acegisecurity.SecurityConfig;
-import net.sf.acegisecurity.context.SecurityContextHolder;
-import net.sf.acegisecurity.intercept.web.FilterInvocation;
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.mock.web.MockHttpServletResponse;
-
-import javax.servlet.ServletException;
-import java.io.IOException;
-
-/**
- * Tests {@link CaptchaChannelProcessor}
- *
- * @author marc antoine Garrigue
- * @version $Id$
- */
-public class CaptchaChannelProcessorTests extends TestCase {
-
- public void testDecideRequestsFirstTestRequests() throws Exception {
- ConfigAttributeDefinition cad = new ConfigAttributeDefinition();
- cad.addConfigAttribute(new SecurityConfig("SOME_IGNORED_ATTRIBUTE"));
- cad.addConfigAttribute(new SecurityConfig(
- "REQUIRES_HUMAN_AFTER_MAX_REQUESTS"));
-
- CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
- SecurityContextHolder.setContext(context);
-
- CaptchaChannelProcessor processor = new CaptchaChannelProcessor();
- CaptchaEntryPoint epoint = new CaptchaEntryPoint();
- epoint.setCaptchaFormUrl("/jcaptcha.do");
- epoint.setIncludeOriginalRequest(false);
-
- processor.setEntryPoint(epoint);
-
- MockHttpServletRequest request = new MockHttpServletRequest();
- request.setQueryString("info=true");
- request.setServerName("localhost");
- request.setContextPath("/demo");
- request.setServletPath("/restricted");
- request.setScheme("http");
- request.setServerPort(8000);
-
- MockHttpServletResponse response = new MockHttpServletResponse();
- MockFilterChain chain = new MockFilterChain();
- FilterInvocation fi = new FilterInvocation(request, response, chain);
-
- processor.decide(fi, cad);
- assertEquals(response.getRedirectedUrl(),
- "http://localhost:8000/demo/jcaptcha.do");
-
- processor.setMaxRequestsBeforeFirstTest(1);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals(response.getRedirectedUrl(), null);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals(response.getRedirectedUrl(),
- "http://localhost:8000/demo/jcaptcha.do");
-
- processor.setMaxRequestsBeforeFirstTest(2);
- processor.setMaxMillisBeforeReTest(0);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals(null, response.getRedirectedUrl());
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
- }
-
- public void testDecideRequestsFirstTestMillis() throws Exception {
- ConfigAttributeDefinition cad = new ConfigAttributeDefinition();
- cad.addConfigAttribute(new SecurityConfig("SOME_IGNORED_ATTRIBUTE"));
- cad.addConfigAttribute(new SecurityConfig(
- "REQUIRES_HUMAN_AFTER_MAX_MILLIS"));
-
- CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
- SecurityContextHolder.setContext(context);
-
- CaptchaChannelProcessor processor = new CaptchaChannelProcessor();
- CaptchaEntryPoint epoint = new CaptchaEntryPoint();
- epoint.setCaptchaFormUrl("/jcaptcha.do");
- epoint.setIncludeOriginalRequest(false);
-
- processor.setEntryPoint(epoint);
-
- MockHttpServletRequest request = new MockHttpServletRequest();
- request.setQueryString("info=true");
- request.setServerName("localhost");
- request.setContextPath("/demo");
- request.setServletPath("/restricted");
- request.setScheme("http");
- request.setServerPort(8000);
-
- MockHttpServletResponse response = new MockHttpServletResponse();
- MockFilterChain chain = new MockFilterChain();
- FilterInvocation fi = new FilterInvocation(request, response, chain);
-
- processor.decide(fi, cad);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
-
- processor.setMaxRequestsBeforeFirstTest(1);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals(null, response.getRedirectedUrl());
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
-
- processor.setMaxRequestsBeforeFirstTest(2);
- processor.setMaxRequestsBeforeReTest(0);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals(null, response.getRedirectedUrl());
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
-
- }
-
- public void testDecideRequestsReTest() throws Exception {
- ConfigAttributeDefinition cad = new ConfigAttributeDefinition();
- cad.addConfigAttribute(new SecurityConfig("SOME_IGNORED_ATTRIBUTE"));
- cad.addConfigAttribute(new SecurityConfig(
- "REQUIRES_HUMAN_AFTER_MAX_REQUESTS"));
-
- CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
- SecurityContextHolder.setContext(context);
-
- CaptchaChannelProcessor processor = new CaptchaChannelProcessor();
- CaptchaEntryPoint epoint = new CaptchaEntryPoint();
- epoint.setCaptchaFormUrl("/jcaptcha.do");
- epoint.setIncludeOriginalRequest(false);
-
- processor.setEntryPoint(epoint);
-
- MockHttpServletRequest request = new MockHttpServletRequest();
- request.setQueryString("info=true");
- request.setServerName("localhost");
- request.setContextPath("/demo");
- request.setServletPath("/restricted");
- request.setScheme("http");
- request.setServerPort(8000);
-
- MockHttpServletResponse response = new MockHttpServletResponse();
- MockFilterChain chain = new MockFilterChain();
- FilterInvocation fi = new FilterInvocation(request, response, chain);
-
- processor.decide(fi, cad);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
-
- processor.setMaxRequestsBeforeFirstTest(1);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals(response.getRedirectedUrl(), null);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
-
- processor.setMaxRequestsBeforeReTest(2);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
-
- context.setHuman();
- SecurityContextHolder.setContext(context);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals(null, response.getRedirectedUrl());
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals(null, response.getRedirectedUrl());
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
-
- processor.setMaxMillisBeforeReTest(0);
- context.setHuman();
- SecurityContextHolder.setContext(context);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals(null, response.getRedirectedUrl());
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals(null, response.getRedirectedUrl());
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
-
- context.setHuman();
- SecurityContextHolder.setContext(context);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals(null, response.getRedirectedUrl());
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals(null, response.getRedirectedUrl());
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
- }
-
- private MockHttpServletResponse decideWithNewResponse(
- ConfigAttributeDefinition cad, CaptchaChannelProcessor processor,
- MockHttpServletRequest request) throws IOException,
- ServletException {
- MockHttpServletResponse response;
- MockFilterChain chain;
- FilterInvocation fi;
- response = new MockHttpServletResponse();
- chain = new MockFilterChain();
- fi = new FilterInvocation(request, response, chain);
- processor.decide(fi, cad);
- return response;
- }
-
- public void testDecideRejectsNulls() throws Exception {
- CaptchaChannelProcessor processor = new CaptchaChannelProcessor();
- processor.setEntryPoint(new CaptchaEntryPoint());
- processor.afterPropertiesSet();
-
- try {
- processor.decide(null, null);
- fail("Should have thrown IllegalArgumentException");
- } catch (IllegalArgumentException expected) {
- assertTrue(true);
- }
- }
-
- public void testDecideMillis() throws Exception {
- ConfigAttributeDefinition cad = new ConfigAttributeDefinition();
- cad.addConfigAttribute(new SecurityConfig("SOME_IGNORED_ATTRIBUTE"));
- cad.addConfigAttribute(new SecurityConfig(
- "REQUIRES_HUMAN_AFTER_MAX_MILLIS"));
-
- CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
- SecurityContextHolder.setContext(context);
-
- CaptchaChannelProcessor processor = new CaptchaChannelProcessor();
- CaptchaEntryPoint epoint = new CaptchaEntryPoint();
- epoint.setCaptchaFormUrl("/jcaptcha.do");
- epoint.setIncludeOriginalRequest(false);
-
- processor.setEntryPoint(epoint);
-
- MockHttpServletRequest request = new MockHttpServletRequest();
- request.setQueryString("info=true");
- request.setServerName("localhost");
- request.setContextPath("/demo");
- request.setServletPath("/restricted");
- request.setScheme("http");
- request.setServerPort(8000);
-
- MockHttpServletResponse response = new MockHttpServletResponse();
- MockFilterChain chain = new MockFilterChain();
- FilterInvocation fi = new FilterInvocation(request, response, chain);
-
- processor.decide(fi, cad);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
-
- processor.setMaxRequestsBeforeFirstTest(1);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals(response.getRedirectedUrl(), null);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
-
- processor.setMaxMillisBeforeReTest(100);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
-
- context.setHuman();
- SecurityContextHolder.setContext(context);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals(null, response.getRedirectedUrl());
-
- waitFor(100);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
-
- processor.setMaxRequestsBeforeReTest(0);
- context.setHuman();
- SecurityContextHolder.setContext(context);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals(null, response.getRedirectedUrl());
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals(null, response.getRedirectedUrl());
-
- waitFor(100);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
-
- context.setHuman();
- SecurityContextHolder.setContext(context);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals(null, response.getRedirectedUrl());
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals(null, response.getRedirectedUrl());
-
- waitFor(100);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
- }
-
- public void testDecideBoth() throws Exception {
- ConfigAttributeDefinition cad = new ConfigAttributeDefinition();
- cad.addConfigAttribute(new SecurityConfig("SOME_IGNORED_ATTRIBUTE"));
- cad.addConfigAttribute(new SecurityConfig(
- "REQUIRES_HUMAN_AFTER_MAX_MILLIS"));
- cad.addConfigAttribute(new SecurityConfig(
- "REQUIRES_HUMAN_AFTER_MAX_REQUESTS"));
-
- CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
- SecurityContextHolder.setContext(context);
-
- CaptchaChannelProcessor processor = new CaptchaChannelProcessor();
- CaptchaEntryPoint epoint = new CaptchaEntryPoint();
- epoint.setCaptchaFormUrl("/jcaptcha.do");
- epoint.setIncludeOriginalRequest(false);
-
- processor.setEntryPoint(epoint);
-
- MockHttpServletRequest request = new MockHttpServletRequest();
- request.setQueryString("info=true");
- request.setServerName("localhost");
- request.setContextPath("/demo");
- request.setServletPath("/restricted");
- request.setScheme("http");
- request.setServerPort(8000);
-
- MockHttpServletResponse response = new MockHttpServletResponse();
- MockFilterChain chain = new MockFilterChain();
- FilterInvocation fi = new FilterInvocation(request, response, chain);
-
- processor.decide(fi, cad);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
-
- processor.setMaxRequestsBeforeFirstTest(1);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals(response.getRedirectedUrl(), null);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
-
- processor.setMaxMillisBeforeReTest(100);
- processor.setMaxRequestsBeforeReTest(2);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
-
- context.setHuman();
- SecurityContextHolder.setContext(context);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals(null, response.getRedirectedUrl());
-
- waitFor(100);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
-
- context.setHuman();
- SecurityContextHolder.setContext(context);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals(null, response.getRedirectedUrl());
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals(null, response.getRedirectedUrl());
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
-
- context.setHuman();
- SecurityContextHolder.setContext(context);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals(null, response.getRedirectedUrl());
-
- waitFor(100);
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
-
- response = decideWithNewResponse(cad, processor, request);
- assertEquals("http://localhost:8000/demo/jcaptcha.do", response
- .getRedirectedUrl());
- }
-
- public void testGettersSetters() {
- CaptchaChannelProcessor processor = new CaptchaChannelProcessor();
- assertEquals("REQUIRES_HUMAN_AFTER_MAX_MILLIS", processor
- .getRequiresHumanAfterMaxMillisKeyword());
- processor.setRequiresHumanAfterMaxMillisKeyword("X");
- assertEquals("X", processor.getRequiresHumanAfterMaxMillisKeyword());
-
- assertEquals("REQUIRES_HUMAN_AFTER_MAX_REQUESTS", processor
- .getRequiresHumanAfterMaxRequestsKeyword());
- processor.setRequiresHumanAfterMaxRequestsKeyword("Y");
- assertEquals("Y", processor.getRequiresHumanAfterMaxRequestsKeyword());
-
- assertEquals(0, processor.getMaxRequestsBeforeFirstTest());
- processor.setMaxRequestsBeforeFirstTest(1);
- assertEquals(1, processor.getMaxRequestsBeforeFirstTest());
-
- assertEquals(-1, processor.getMaxRequestsBeforeReTest());
- processor.setMaxRequestsBeforeReTest(11);
- assertEquals(11, processor.getMaxRequestsBeforeReTest());
-
- assertEquals(-1, processor.getMaxMillisBeforeReTest());
- processor.setMaxMillisBeforeReTest(111);
- assertEquals(111, processor.getMaxMillisBeforeReTest());
-
- assertTrue(processor.getEntryPoint() == null);
- processor.setEntryPoint(new CaptchaEntryPoint());
- assertTrue(processor.getEntryPoint() != null);
- }
-
- public void testMissingEntryPoint() throws Exception {
- CaptchaChannelProcessor processor = new CaptchaChannelProcessor();
- processor.setEntryPoint(null);
-
- try {
- processor.afterPropertiesSet();
- fail("Should have thrown IllegalArgumentException");
- } catch (IllegalArgumentException expected) {
- assertEquals("entryPoint required", expected.getMessage());
- }
- }
-
- public void testMissingKeyword() throws Exception {
- CaptchaChannelProcessor processor = new CaptchaChannelProcessor();
- processor.setRequiresHumanAfterMaxMillisKeyword(null);
-
- try {
- processor.afterPropertiesSet();
- fail("Should have thrown IllegalArgumentException");
- } catch (IllegalArgumentException expected) {
-
- }
- processor.setRequiresHumanAfterMaxMillisKeyword("");
-
- try {
- processor.afterPropertiesSet();
- fail("Should have thrown IllegalArgumentException");
- } catch (IllegalArgumentException expected) {
-
- }
- processor.setRequiresHumanAfterMaxRequestsKeyword("");
-
- try {
- processor.afterPropertiesSet();
- fail("Should have thrown IllegalArgumentException");
- } catch (IllegalArgumentException expected) {
-
- }
-
- processor.setRequiresHumanAfterMaxRequestsKeyword(null);
-
- try {
- processor.afterPropertiesSet();
- fail("Should have thrown IllegalArgumentException");
- } catch (IllegalArgumentException expected) {
-
- }
-
- }
-
- public void testSupports() {
- CaptchaChannelProcessor processor = new CaptchaChannelProcessor();
- assertTrue(processor.supports(new SecurityConfig(processor
- .getRequiresHumanAfterMaxMillisKeyword())));
- assertTrue(processor.supports(new SecurityConfig(processor
- .getRequiresHumanAfterMaxRequestsKeyword())));
-
- assertTrue(processor.supports(new SecurityConfig(
- "REQUIRES_HUMAN_AFTER_MAX_REQUESTS")));
- assertTrue(processor.supports(new SecurityConfig(
- "REQUIRES_HUMAN_AFTER_MAX_MILLIS")));
-
- assertFalse(processor.supports(null));
-
- assertFalse(processor.supports(new SecurityConfig("NOT_SUPPORTED")));
- }
-
- private void waitFor(int time){
- long start=System.currentTimeMillis();
- while(System.currentTimeMillis()= 0);
+ assertTrue("should be less than 0,1 seconde",
+ (context.getLastPassedCaptchaDateInMillis() - now) < 100);
}
public void testSetHuman() {
@@ -39,47 +72,11 @@ public class CaptchaSecurityContextImplTests extends SecurityContextImplTests {
long now = System.currentTimeMillis();
context.setHuman();
assertEquals("should be human", true, context.isHuman());
- assertTrue("should be more than 0", context
- .getLastPassedCaptchaDateInMillis()
- - now >= 0);
- assertTrue("should be less than 0,1 seconde", context
- .getLastPassedCaptchaDateInMillis()
- - now < 100);
- assertEquals("should be 0", 0, context
- .getHumanRestrictedResourcesRequestsCount());
+ assertTrue("should be more than 0",
+ (context.getLastPassedCaptchaDateInMillis() - now) >= 0);
+ assertTrue("should be less than 0,1 seconde",
+ (context.getLastPassedCaptchaDateInMillis() - now) < 100);
+ assertEquals("should be 0", 0,
+ context.getHumanRestrictedResourcesRequestsCount());
}
-
- public void testIncrementRequests() {
- CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
- context.setHuman();
- assertEquals("should be human", true, context.isHuman());
- assertEquals("should be 0", 0, context
- .getHumanRestrictedResourcesRequestsCount());
- context.incrementHumanRestrictedRessoucesRequestsCount();
- assertEquals("should be 1", 1, context
- .getHumanRestrictedResourcesRequestsCount());
- }
-
- public void testResetHuman() {
- CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
- context.setHuman();
- assertEquals("should be human", true, context.isHuman());
- assertEquals("should be 0", 0, context
- .getHumanRestrictedResourcesRequestsCount());
- context.incrementHumanRestrictedRessoucesRequestsCount();
- assertEquals("should be 1", 1, context
- .getHumanRestrictedResourcesRequestsCount());
- long now = System.currentTimeMillis();
- context.setHuman();
- assertEquals("should be 0", 0, context
- .getHumanRestrictedResourcesRequestsCount());
- assertTrue("should be more than 0", context
- .getLastPassedCaptchaDateInMillis()
- - now >= 0);
- assertTrue("should be less than 0,1 seconde", context
- .getLastPassedCaptchaDateInMillis()
- - now < 100);
-
- }
-
}
diff --git a/core/src/test/java/org/acegisecurity/captcha/CaptchaValidationProcessingFilterTests.java b/core/src/test/java/org/acegisecurity/captcha/CaptchaValidationProcessingFilterTests.java
index 688ab47926..e965890c59 100644
--- a/core/src/test/java/org/acegisecurity/captcha/CaptchaValidationProcessingFilterTests.java
+++ b/core/src/test/java/org/acegisecurity/captcha/CaptchaValidationProcessingFilterTests.java
@@ -1,4 +1,4 @@
-/* Copyright 2004 Acegi Technology Pty Limited
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,10 +16,13 @@
package net.sf.acegisecurity.captcha;
import junit.framework.TestCase;
+
import net.sf.acegisecurity.context.SecurityContextHolder;
import net.sf.acegisecurity.util.MockFilterChain;
+
import org.springframework.mock.web.MockHttpServletRequest;
+
/**
* Tests {@link CaptchaValidationProcessingFilter}.
*
@@ -27,9 +30,10 @@ import org.springframework.mock.web.MockHttpServletRequest;
* @version $Id$
*/
public class CaptchaValidationProcessingFilterTests extends TestCase {
+ //~ Methods ================================================================
/*
- */
+ */
public void testAfterPropertiesSet() throws Exception {
CaptchaValidationProcessingFilter filter = new CaptchaValidationProcessingFilter();
@@ -38,54 +42,27 @@ public class CaptchaValidationProcessingFilterTests extends TestCase {
fail("should have thrown an invalid argument exception");
} catch (Exception e) {
assertTrue("should be an InvalidArgumentException",
- IllegalArgumentException.class.isAssignableFrom(e
- .getClass()));
+ IllegalArgumentException.class.isAssignableFrom(e.getClass()));
}
filter.setCaptchaService(new MockCaptchaServiceProxy());
filter.afterPropertiesSet();
filter.setCaptchaValidationParameter(null);
+
try {
filter.afterPropertiesSet();
fail("should have thrown an invalid argument exception");
} catch (Exception e) {
assertTrue("should be an InvalidArgumentException",
- IllegalArgumentException.class.isAssignableFrom(e
- .getClass()));
+ IllegalArgumentException.class.isAssignableFrom(e.getClass()));
}
-
-
}
/*
- * Test method for
- * 'net.sf.acegisecurity.captcha.CaptchaValidationProcessingFilter.doFilter(ServletRequest,
- * ServletResponse, FilterChain)'
- */
- public void testDoFilterWithoutRequestParameter() throws Exception {
- CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
- SecurityContextHolder.setContext(context);
- MockHttpServletRequest request = new MockHttpServletRequest();
- CaptchaValidationProcessingFilter filter = new CaptchaValidationProcessingFilter();
- MockCaptchaServiceProxy service = new MockCaptchaServiceProxy();
- MockFilterChain chain = new MockFilterChain(true);
- filter.setCaptchaService(service);
- filter.doFilter(request, null, chain);
- assertFalse("proxy should not have been called", service.hasBeenCalled);
- assertFalse("context should not have been updated", context.isHuman());
- // test with valid
- service.valid = true;
- filter.doFilter(request, null, chain);
- assertFalse("proxy should not have been called", service.hasBeenCalled);
- assertFalse("context should not have been updated", context.isHuman());
-
- }
-
- /*
- * Test method for
- * 'net.sf.acegisecurity.captcha.CaptchaValidationProcessingFilter.doFilter(ServletRequest,
- * ServletResponse, FilterChain)'
- */
+ * Test method for
+ * 'net.sf.acegisecurity.captcha.CaptchaValidationProcessingFilter.doFilter(ServletRequest,
+ * ServletResponse, FilterChain)'
+ */
public void testDoFilterWithRequestParameter() throws Exception {
CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
SecurityContextHolder.setContext(context);
@@ -93,10 +70,7 @@ public class CaptchaValidationProcessingFilterTests extends TestCase {
MockHttpServletRequest request = new MockHttpServletRequest();
CaptchaValidationProcessingFilter filter = new CaptchaValidationProcessingFilter();
- request
- .addParameter(
- filter.getCaptchaValidationParameter(),
- "");
+ request.addParameter(filter.getCaptchaValidationParameter(), "");
MockCaptchaServiceProxy service = new MockCaptchaServiceProxy();
MockFilterChain chain = new MockFilterChain(true);
@@ -104,12 +78,36 @@ public class CaptchaValidationProcessingFilterTests extends TestCase {
filter.doFilter(request, null, chain);
assertTrue("should have been called", service.hasBeenCalled);
assertFalse("context should not have been updated", context.isHuman());
+
// test with valid
service.valid = true;
filter.doFilter(request, null, chain);
assertTrue("should have been called", service.hasBeenCalled);
assertTrue("context should have been updated", context.isHuman());
-
}
+ /*
+ * Test method for
+ * 'net.sf.acegisecurity.captcha.CaptchaValidationProcessingFilter.doFilter(ServletRequest,
+ * ServletResponse, FilterChain)'
+ */
+ public void testDoFilterWithoutRequestParameter() throws Exception {
+ CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
+ SecurityContextHolder.setContext(context);
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ CaptchaValidationProcessingFilter filter = new CaptchaValidationProcessingFilter();
+ MockCaptchaServiceProxy service = new MockCaptchaServiceProxy();
+ MockFilterChain chain = new MockFilterChain(true);
+ filter.setCaptchaService(service);
+ filter.doFilter(request, null, chain);
+ assertFalse("proxy should not have been called", service.hasBeenCalled);
+ assertFalse("context should not have been updated", context.isHuman());
+
+ // test with valid
+ service.valid = true;
+ filter.doFilter(request, null, chain);
+ assertFalse("proxy should not have been called", service.hasBeenCalled);
+ assertFalse("context should not have been updated", context.isHuman());
+ }
}
diff --git a/core/src/test/java/org/acegisecurity/captcha/MockCaptchaServiceProxy.java b/core/src/test/java/org/acegisecurity/captcha/MockCaptchaServiceProxy.java
index 6b3197e9ee..d1cf9c2a05 100644
--- a/core/src/test/java/org/acegisecurity/captcha/MockCaptchaServiceProxy.java
+++ b/core/src/test/java/org/acegisecurity/captcha/MockCaptchaServiceProxy.java
@@ -1,4 +1,4 @@
-/* Copyright 2004 Acegi Technology Pty Limited
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,19 +16,22 @@
package net.sf.acegisecurity.captcha;
/**
+ * DOCUMENT ME!
+ *
* @author marc antoine Garrigue
* @version $Id$
*/
public class MockCaptchaServiceProxy implements CaptchaServiceProxy {
-
- public boolean valid = false;
+ //~ Instance fields ========================================================
public boolean hasBeenCalled = false;
+ public boolean valid = false;
+
+ //~ Methods ================================================================
public boolean validateReponseForId(String id, Object response) {
hasBeenCalled = true;
+
return valid;
-
}
-
}
diff --git a/core/src/test/java/org/acegisecurity/captcha/TestOnceAfterMaxRequestsCaptchaChannelProcessorTests.java b/core/src/test/java/org/acegisecurity/captcha/TestOnceAfterMaxRequestsCaptchaChannelProcessorTests.java
new file mode 100644
index 0000000000..7ac277750c
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/captcha/TestOnceAfterMaxRequestsCaptchaChannelProcessorTests.java
@@ -0,0 +1,84 @@
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.sf.acegisecurity.captcha;
+
+import junit.framework.*;
+
+import net.sf.acegisecurity.captcha.TestOnceAfterMaxRequestsCaptchaChannelProcessor;
+
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author $author$
+ * @version $Revision$
+ */
+public class TestOnceAfterMaxRequestsCaptchaChannelProcessorTests
+ extends TestCase {
+ //~ Instance fields ========================================================
+
+ TestOnceAfterMaxRequestsCaptchaChannelProcessor testOnceAfterMaxRequestsCaptchaChannelProcessor;
+
+ //~ Methods ================================================================
+
+ public void testIsContextValidConcerningHumanity()
+ throws Exception {
+ testOnceAfterMaxRequestsCaptchaChannelProcessor.setThresold(1);
+
+ CaptchaSecurityContextImpl context = new CaptchaSecurityContextImpl();
+ assertTrue(testOnceAfterMaxRequestsCaptchaChannelProcessor
+ .isContextValidConcerningHumanity(context));
+
+ context.incrementHumanRestrictedRessoucesRequestsCount();
+
+ testOnceAfterMaxRequestsCaptchaChannelProcessor.setThresold(-1);
+ assertFalse(testOnceAfterMaxRequestsCaptchaChannelProcessor
+ .isContextValidConcerningHumanity(context));
+
+ testOnceAfterMaxRequestsCaptchaChannelProcessor.setThresold(3);
+ assertTrue(testOnceAfterMaxRequestsCaptchaChannelProcessor
+ .isContextValidConcerningHumanity(context));
+ context.incrementHumanRestrictedRessoucesRequestsCount();
+ assertTrue(testOnceAfterMaxRequestsCaptchaChannelProcessor
+ .isContextValidConcerningHumanity(context));
+ context.incrementHumanRestrictedRessoucesRequestsCount();
+ assertFalse(testOnceAfterMaxRequestsCaptchaChannelProcessor
+ .isContextValidConcerningHumanity(context));
+ context.setHuman();
+
+ for (int i = 0;
+ i < (2 * testOnceAfterMaxRequestsCaptchaChannelProcessor
+ .getThresold()); i++) {
+ assertTrue(testOnceAfterMaxRequestsCaptchaChannelProcessor
+ .isContextValidConcerningHumanity(context));
+ }
+ }
+
+ public void testNewContext() {
+ CaptchaSecurityContextImpl context = new CaptchaSecurityContextImpl();
+
+ assertFalse(testOnceAfterMaxRequestsCaptchaChannelProcessor
+ .isContextValidConcerningHumanity(context));
+ testOnceAfterMaxRequestsCaptchaChannelProcessor.setThresold(1);
+ assertTrue(testOnceAfterMaxRequestsCaptchaChannelProcessor
+ .isContextValidConcerningHumanity(context));
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ testOnceAfterMaxRequestsCaptchaChannelProcessor = new TestOnceAfterMaxRequestsCaptchaChannelProcessor();
+ }
+}