mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-03-09 06:50:05 +00:00
SEC-2
Refactor the CaptchaChannelProcessor and extract a CaptchaChannelProcessor that is an abstract class and add its implementations. Jalopy on all java files.
This commit is contained in:
parent
ac05c5a843
commit
5235727d23
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* return false if ny CaptchaChannelProcessorTemplate of mapped urls has been
|
||||
* requested more than thresold; <br>
|
||||
* Default keyword : REQUIRES_CAPTCHA_ABOVE_THRESOLD_REQUESTS
|
||||
* </p>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* return false if thresold is greater than millis since last captcha test has occured;<br>
|
||||
* Default keyword : REQUIRES_CAPTCHA_AFTER_THRESOLD_IN_MILLIS
|
||||
* </p>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* return false if thresold is lower than average time millis between any
|
||||
* CaptchaChannelProcessorTemplate mapped urls requests and is human;<br>
|
||||
* Default keyword : REQUIRES_CAPTCHA_AFTER_THRESOLD_IN_MILLIS <br>
|
||||
* Note : before first humanity check
|
||||
* </p>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Ensures the user has enougth human privileges by review of the
|
||||
* {@link net.sf.acegisecurity.captcha.CaptchaSecurityContext}.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* The class takes 3 required attributes :
|
||||
* <ul>
|
||||
* <li>maxRequestsBeforeFirstTest : used by
|
||||
* {@link #getRequiresHumanAfterMaxRequestsKeyword()} and
|
||||
* {@link #getRequiresHumanAfterMaxMillisKeyword()}<br>
|
||||
* default value = 0 (ie first request).</li>
|
||||
* <li>maxRequestsBeforeReTest : used by
|
||||
* {@link #getRequiresHumanAfterMaxMillisKeyword()}<br>
|
||||
* default value = -1 (ie disabled, once in a {@link CaptchaSecurityContext}'s
|
||||
* life).</li>
|
||||
* <li>maxMillisBeforeReTest: used by
|
||||
* {@link #getRequiresHumanAfterMaxMillisKeyword()} <br>
|
||||
* default value = -1 (ie disabled, once in a {@link CaptchaSecurityContext}'s
|
||||
* life).</li>
|
||||
* </ul>
|
||||
* The class responds to two case-sensitive keywords :
|
||||
* <ul>
|
||||
* <li>{@link #getRequiresHumanAfterMaxRequestsKeyword()} <br>
|
||||
* default value = <code>REQUIRES_HUMAN_AFTER_MAX_REQUESTS</code> <br>
|
||||
* if detected, checks if :
|
||||
* <ul>
|
||||
* <ul>
|
||||
* <li><code>{@link CaptchaSecurityContext#isHuman()} == true</code> </li>
|
||||
* <li><b>or</b></li>
|
||||
* <li><code>{@link CaptchaSecurityContext#getHumanRestrictedResourcesRequestsCount()} < maxRequestsBeforeFirstTest</code></b></li>
|
||||
* </ul>
|
||||
* <li><b>and</b></li>
|
||||
* <ul>
|
||||
* <li><code>{@link CaptchaSecurityContext#getHumanRestrictedResourcesRequestsCount()} < maxRequestsBeforeReTest </code></li>
|
||||
* <li><b>or</b></li>
|
||||
* <li><code>maxRequestsBeforeReTest < 0 </code></b></li>
|
||||
* </ul>
|
||||
* </ul>
|
||||
* </li>
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* <li>{@link #getRequiresHumanAfterMaxRequestsKeyword()} <br>
|
||||
* default value = <code>REQUIRES_HUMAN_AFTER_MAX_MILLIS</code> <br>
|
||||
* if detected, checks if :
|
||||
*
|
||||
* <ul>
|
||||
* <ul>
|
||||
* <li><code>{@link CaptchaSecurityContext#isHuman()} == true</code> </li>
|
||||
* <li><b>or</b></li>
|
||||
* <li><code>{@link CaptchaSecurityContext#getHumanRestrictedResourcesRequestsCount()} < =maxRequestsBeforeFirstTest</code></b></li>
|
||||
* </ul>
|
||||
* <li><b>and</b></li>
|
||||
* <ul>
|
||||
* <li><code>System.currentTimeMillis()-{@link CaptchaSecurityContext#getLastPassedCaptchaDateInMillis()} <= maxMillisBeforeReTest </code></li>
|
||||
* <li><b>or</b></li>
|
||||
* <li><code>maxMillisBeforeReTest < 0 </code></b></li>
|
||||
* </ul>
|
||||
* </ul>
|
||||
* </li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* <u>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})
|
||||
* </u><br>
|
||||
* <ul>
|
||||
* <li>Once in a session and at first request : use the <br>
|
||||
* REQUIRES_HUMAN_AFTER_MAX_REQUESTS keyword <br>
|
||||
* with a maxRequestsBeforeFirstTest=0<br>
|
||||
* and a maxRequestsBeforeReTest=-1<br>
|
||||
* </li>
|
||||
* <br>
|
||||
*
|
||||
* <li>Once in a session and only after 3 requests : use the <br>
|
||||
* REQUIRES_HUMAN_AFTER_MAX_REQUESTS keyword <br>
|
||||
* with a maxRequestsBeforeFirstTest=3</li>
|
||||
* and a maxRequestsBeforeReTest=-1<br>
|
||||
* <br>
|
||||
*
|
||||
* <li>Every request and only after 5 requests : use the <br>
|
||||
* REQUIRES_HUMAN_AFTER_MAX_REQUESTS <br>
|
||||
* with a maxRequestsBeforeReTest=0<br>
|
||||
* and a maxRequestsBeforeFirstTest=5</li>
|
||||
* <br>
|
||||
*
|
||||
* <li>Every 3 requests and every minute : use the <br>
|
||||
* REQUIRES_HUMAN_AFTER_MAX_MILLIS keywords <br>
|
||||
* with a maxMillisBeforeReTest=6000 <br>
|
||||
* and a maxRequestsBeforeFirstTest=3</li>
|
||||
* <br>
|
||||
*
|
||||
* <li>Every 20 requests and every hour and only after 100 requests : use the
|
||||
* <br>
|
||||
* REQUIRES_HUMAN_AFTER_MAX_REQUESTS <br>
|
||||
* and the REQUIRES_HUMAN_AFTER_MAX_MILLIS <br>
|
||||
* and the REQUIRES_HUMAN_AFTER_MAX_REQUESTS keywords <br>
|
||||
* with a maxRequestsBeforeReTest=20 <br>
|
||||
* and a maxMillisBeforeReTest=3600000 <br>
|
||||
* and a maxRequestsBeforeFirstTest=1000</li>
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
*
|
||||
* @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());
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 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)
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* The component uses 2 main parameters for its configuration :
|
||||
*
|
||||
* <ul>
|
||||
* <li>
|
||||
* a keyword to be mapped to urls in the {@link
|
||||
* net.sf.acegisecurity.securechannel.ChannelProcessingFilter} configuration<br>
|
||||
* default value provided by sub classes.
|
||||
* </li>
|
||||
* <li>
|
||||
* and a thresold : used by the routine {@link
|
||||
* #isContextValidConcerningHumanity(CaptchaSecurityContext)} to evaluate
|
||||
* whether the {@link CaptchaSecurityContext} is valid default value = 0
|
||||
* </li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
* @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());
|
||||
}
|
||||
}
|
@ -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. <br/>
|
||||
* <p/>
|
||||
* This entry point can force the use of SSL : see {@link #getForceHttps()}<br/>
|
||||
* <p/>
|
||||
* This entry point allows internal OR external redirect : see {@link #setOutsideWebApp(boolean)}<br/>/ Original request
|
||||
* can be added to the redirect path using a custom translation : see {@link #setIncludeOriginalRequest(boolean)} <br/>
|
||||
* Original request is translated using URLEncoding and the following translation mapping in the redirect url : <ul>
|
||||
* <li>original url => {@link #getOriginalRequestUrlParameterName()}</li> <li> If {@link
|
||||
* #isIncludeOriginalParameters()}</li> <li>original method => {@link #getOriginalRequestMethodParameterName()} </li>
|
||||
* <li>original parameters => {@link #getOriginalRequestParametersParameterName()} </li> <li>The orinial parameters
|
||||
* string is contructed using :</li> <ul> <li>a parameter separator {@link #getOriginalRequestParametersSeparator()}
|
||||
* </li> <li>a parameter name value pair separator for each parameter {@link #getOriginalRequestParametersNameValueSeparator()}
|
||||
* </li> </ul> </ul>
|
||||
* <p/>
|
||||
* <p/>
|
||||
* <p/>
|
||||
* <br/> Default values :<br/> forceHttps = false<br/> includesOriginalRequest = true<br/> includesOriginalParameters =
|
||||
* false<br/> isOutsideWebApp=false<br/> originalRequestUrlParameterName ="original_requestUrl" <br/>
|
||||
* originalRequestParametersParameterName = "original_request_parameters";<br/>
|
||||
* <p/>
|
||||
* originalRequestParametersNameValueSeparator = "@@"; <br/>
|
||||
* <p/>
|
||||
* originalRequestParametersSeparator = ";;"; <br/>
|
||||
* <p/>
|
||||
* originalRequestMethodParameterName = "original_request_method"; <br/>
|
||||
* <p/>
|
||||
* urlEncodingCharset = "UTF-8"; <br/>
|
||||
* The captcha entry point : redirect to the captcha test page. <br>
|
||||
*
|
||||
* <p>
|
||||
* This entry point can force the use of SSL : see {@link #getForceHttps()}<br>
|
||||
* </p>
|
||||
* This entry point allows internal OR external redirect : see {@link #setOutsideWebApp(boolean)}<br>
|
||||
* / Original request can be added to the redirect path using a custom
|
||||
* translation : see {@link #setIncludeOriginalRequest(boolean)}<br>
|
||||
* Original request is translated using URLEncoding and the following
|
||||
* translation mapping in the redirect url :
|
||||
*
|
||||
* <ul>
|
||||
* <li>
|
||||
* original url => {@link #getOriginalRequestUrlParameterName()}
|
||||
* </li>
|
||||
* <li>
|
||||
* If {@link #isIncludeOriginalParameters()}
|
||||
* </li>
|
||||
* <li>
|
||||
* original method => {@link #getOriginalRequestMethodParameterName()}
|
||||
* </li>
|
||||
* <li>
|
||||
* original parameters => {@link #getOriginalRequestParametersParameterName()}
|
||||
* </li>
|
||||
* <li>
|
||||
* The original parameters string is contructed using :
|
||||
*
|
||||
* <ul>
|
||||
* <li>
|
||||
* a parameter separator {@link #getOriginalRequestParametersSeparator()}
|
||||
* </li>
|
||||
* <li>
|
||||
* a parameter name value pair separator for each parameter {@link
|
||||
* #getOriginalRequestParametersNameValueSeparator()}
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* <br><br>
|
||||
* Default values :<br>
|
||||
* forceHttps = false<br>
|
||||
* includesOriginalRequest = true<br>
|
||||
* includesOriginalParameters = false<br>
|
||||
* isOutsideWebApp=false<br>
|
||||
* originalRequestUrlParameterName =original_requestUrl <br>
|
||||
* originalRequestParametersParameterName = original_request_parameters<br>
|
||||
* originalRequestParametersNameValueSeparator = __ <br>
|
||||
* originalRequestParametersSeparator = ;; <br>
|
||||
* originalRequestMethodParameterName = original_request_method <br>
|
||||
* urlEncodingCharset = UTF-8<br>
|
||||
*
|
||||
* @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 <code>CaptchaProcessingFilter</code> login page can be
|
||||
* found. Should be relative to the web-app context path, and include a
|
||||
* leading <code>/</code>
|
||||
*
|
||||
* @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 <code>https</code>,
|
||||
* 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
|
||||
* <code>https</code>, 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 <code>CaptchaProcessingFilter</code> login page can be found. Should be relative to the web-app
|
||||
* context path, and include a leading <code>/</code>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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}. <br/> 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. <br/> <br/> 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. <br/> <br/> This filter
|
||||
* should only be used in conjunction with the {@link CaptchaSecurityContext} <br/> <br/>
|
||||
* Filter for web integration of the {@link CaptchaServiceProxy}. <br>
|
||||
* 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. <br>
|
||||
* 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. <br>
|
||||
* This filter should only be used in conjunction with the {@link
|
||||
* CaptchaSecurityContext}<br>
|
||||
*
|
||||
* @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 {}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* return false if ny CaptchaChannelProcessorTemplate mapped urls has been
|
||||
* requested more than thresold and humanity is false; <br>
|
||||
* Default keyword : REQUIRES_CAPTCHA_ONCE_ABOVE_THRESOLD_REQUESTS
|
||||
* </p>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,12 @@
|
||||
<html>
|
||||
<body>
|
||||
Captcha classes.
|
||||
Captcha classes. Contains :<br/>
|
||||
<ul>
|
||||
<li>a CaptchaSecurityContext that overrides the default SecurityContext and holds some captcha related informations</li>
|
||||
<li>an abstract CaptchaChannelProcessorTemplate and its implementations that test this context according to the configuration</li>
|
||||
<li>a CaptchaServiceProxy and a CaptchaValidationProcessingFilter that alows to validate a captcha response and to update the CaptchaSecurity</li>
|
||||
<li>a CaptchaEntryPoint that redirects to a captcha page if the CaptchaChannelProcessor implementation decide so</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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.
|
||||
* <pre><code>
|
||||
* context.setHuman();
|
||||
* assertFalse(alwaysTestAfterTimeInMillisCaptchaChannelProcessor.isContextValidConcerningHumanity(context));
|
||||
* </code></pre>
|
||||
* This should be the case for most environements unless
|
||||
*
|
||||
* <ul>
|
||||
* <li>
|
||||
* you run it on a good old TRS-80
|
||||
* </li>
|
||||
* <li>
|
||||
* you start M$office during this test ;)
|
||||
* </li>
|
||||
* </ul>
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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()<start+time){
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
@ -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,15 +16,19 @@
|
||||
package net.sf.acegisecurity.captcha;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import net.sf.acegisecurity.MockPortResolver;
|
||||
import net.sf.acegisecurity.util.PortMapperImpl;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
import java.net.URLEncoder;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link CaptchaEntryPoint}.
|
||||
*
|
||||
@ -32,9 +36,10 @@ import java.util.Map;
|
||||
* @version $Id$
|
||||
*/
|
||||
public class CaptchaEntryPointTests extends TestCase {
|
||||
//~ Methods ================================================================
|
||||
|
||||
// ~ Methods
|
||||
// ================================================================
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
@ -52,8 +57,8 @@ public class CaptchaEntryPointTests extends TestCase {
|
||||
ep.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("captchaFormUrl must be specified", expected
|
||||
.getMessage());
|
||||
assertEquals("captchaFormUrl must be specified",
|
||||
expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,10 +84,8 @@ public class CaptchaEntryPointTests extends TestCase {
|
||||
ep.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("portResolver must be specified", expected
|
||||
.getMessage());
|
||||
assertEquals("portResolver must be specified", expected.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void testGettersSetters() {
|
||||
@ -94,7 +97,8 @@ public class CaptchaEntryPointTests extends TestCase {
|
||||
assertTrue(ep.getPortMapper() != null);
|
||||
assertTrue(ep.getPortResolver() != null);
|
||||
|
||||
assertEquals("original_requestUrl", ep.getOriginalRequestUrlParameterName());
|
||||
assertEquals("original_requestUrl",
|
||||
ep.getOriginalRequestUrlParameterName());
|
||||
ep.setOriginalRequestUrlParameterName("Z");
|
||||
assertEquals("Z", ep.getOriginalRequestUrlParameterName());
|
||||
|
||||
@ -110,10 +114,10 @@ public class CaptchaEntryPointTests extends TestCase {
|
||||
assertFalse(ep.getForceHttps());
|
||||
ep.setForceHttps(true);
|
||||
assertTrue(ep.getForceHttps());
|
||||
|
||||
}
|
||||
|
||||
public void testHttpsOperationFromOriginalHttpUrl() throws Exception {
|
||||
public void testHttpsOperationFromOriginalHttpUrl()
|
||||
throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
request.setRequestURI("/some_path");
|
||||
@ -134,22 +138,22 @@ public class CaptchaEntryPointTests extends TestCase {
|
||||
ep.afterPropertiesSet();
|
||||
|
||||
ep.commence(request, response);
|
||||
assertEquals("https://www.example.com/bigWebApp/hello", response
|
||||
.getRedirectedUrl());
|
||||
assertEquals("https://www.example.com/bigWebApp/hello",
|
||||
response.getRedirectedUrl());
|
||||
|
||||
request.setServerPort(8080);
|
||||
response = new MockHttpServletResponse();
|
||||
ep.setPortResolver(new MockPortResolver(8080, 8443));
|
||||
ep.commence(request, response);
|
||||
assertEquals("https://www.example.com:8443/bigWebApp/hello", response
|
||||
.getRedirectedUrl());
|
||||
assertEquals("https://www.example.com:8443/bigWebApp/hello",
|
||||
response.getRedirectedUrl());
|
||||
|
||||
// Now test an unusual custom HTTP:HTTPS is handled properly
|
||||
request.setServerPort(8888);
|
||||
response = new MockHttpServletResponse();
|
||||
ep.commence(request, response);
|
||||
assertEquals("https://www.example.com:8443/bigWebApp/hello", response
|
||||
.getRedirectedUrl());
|
||||
assertEquals("https://www.example.com:8443/bigWebApp/hello",
|
||||
response.getRedirectedUrl());
|
||||
|
||||
PortMapperImpl portMapper = new PortMapperImpl();
|
||||
Map map = new HashMap();
|
||||
@ -168,11 +172,12 @@ public class CaptchaEntryPointTests extends TestCase {
|
||||
ep.afterPropertiesSet();
|
||||
|
||||
ep.commence(request, response);
|
||||
assertEquals("https://www.example.com:9999/bigWebApp/hello", response
|
||||
.getRedirectedUrl());
|
||||
assertEquals("https://www.example.com:9999/bigWebApp/hello",
|
||||
response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
public void testHttpsOperationFromOriginalHttpsUrl() throws Exception {
|
||||
public void testHttpsOperationFromOriginalHttpsUrl()
|
||||
throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
request.setRequestURI("/some_path");
|
||||
@ -193,15 +198,15 @@ public class CaptchaEntryPointTests extends TestCase {
|
||||
ep.afterPropertiesSet();
|
||||
|
||||
ep.commence(request, response);
|
||||
assertEquals("https://www.example.com/bigWebApp/hello", response
|
||||
.getRedirectedUrl());
|
||||
assertEquals("https://www.example.com/bigWebApp/hello",
|
||||
response.getRedirectedUrl());
|
||||
|
||||
request.setServerPort(8443);
|
||||
response = new MockHttpServletResponse();
|
||||
ep.setPortResolver(new MockPortResolver(8080, 8443));
|
||||
ep.commence(request, response);
|
||||
assertEquals("https://www.example.com:8443/bigWebApp/hello", response
|
||||
.getRedirectedUrl());
|
||||
assertEquals("https://www.example.com:8443/bigWebApp/hello",
|
||||
response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
public void testNormalOperation() throws Exception {
|
||||
@ -212,7 +217,6 @@ public class CaptchaEntryPointTests extends TestCase {
|
||||
ep.afterPropertiesSet();
|
||||
ep.setIncludeOriginalRequest(false);
|
||||
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/some_path");
|
||||
request.setContextPath("/bigWebApp");
|
||||
@ -225,12 +229,12 @@ public class CaptchaEntryPointTests extends TestCase {
|
||||
|
||||
ep.afterPropertiesSet();
|
||||
ep.commence(request, response);
|
||||
assertEquals("http://www.example.com/bigWebApp/hello", response
|
||||
.getRedirectedUrl());
|
||||
assertEquals("http://www.example.com/bigWebApp/hello",
|
||||
response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
public void testOperationWhenHttpsRequestsButHttpsPortUnknown()
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
CaptchaEntryPoint ep = new CaptchaEntryPoint();
|
||||
ep.setCaptchaFormUrl("/hello");
|
||||
ep.setPortMapper(new PortMapperImpl());
|
||||
@ -255,16 +259,18 @@ public class CaptchaEntryPointTests extends TestCase {
|
||||
|
||||
// Response doesn't switch to HTTPS, as we didn't know HTTP port 8888 to
|
||||
// HTTP port mapping
|
||||
assertEquals("http://www.example.com:8888/bigWebApp/hello", response
|
||||
.getRedirectedUrl());
|
||||
assertEquals("http://www.example.com:8888/bigWebApp/hello",
|
||||
response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
public void testOperationWithOriginalRequestIncludes() throws Exception {
|
||||
public void testOperationWithOriginalRequestIncludes()
|
||||
throws Exception {
|
||||
CaptchaEntryPoint ep = new CaptchaEntryPoint();
|
||||
ep.setCaptchaFormUrl("/hello");
|
||||
|
||||
PortMapperImpl mapper = new PortMapperImpl();
|
||||
mapper.getTranslatedPortMappings().put(new Integer(8888),
|
||||
new Integer(1234));
|
||||
new Integer(1234));
|
||||
ep.setPortMapper(mapper);
|
||||
|
||||
ep.setPortResolver(new MockPortResolver(8888, 1234));
|
||||
@ -276,30 +282,26 @@ public class CaptchaEntryPointTests extends TestCase {
|
||||
request.setRequestURI("/some_path");
|
||||
request.setScheme("http");
|
||||
request.setServerName("www.example.com");
|
||||
|
||||
// request.setContextPath("/bigWebApp");
|
||||
// TODO correct this when the getRequestUrl from mock works...
|
||||
|
||||
request.setServerPort(8888); // NB: Port we can't resolve
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
ep.afterPropertiesSet();
|
||||
ep.commence(request, response);
|
||||
assertEquals(
|
||||
"http://www.example.com:8888/hello?original_requestUrl="
|
||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8")
|
||||
+ "&original_request_method=post",
|
||||
response.getRedirectedUrl());
|
||||
assertEquals("http://www.example.com:8888/hello?original_requestUrl="
|
||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8")
|
||||
+ "&original_request_method=post", response.getRedirectedUrl());
|
||||
|
||||
// test the query params
|
||||
request.addParameter("name", "value");
|
||||
response = new MockHttpServletResponse();
|
||||
ep.commence(request, response);
|
||||
assertEquals(
|
||||
"http://www.example.com:8888/hello?original_requestUrl="
|
||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8")
|
||||
+ "&original_request_method=post",
|
||||
response.getRedirectedUrl());
|
||||
assertEquals("http://www.example.com:8888/hello?original_requestUrl="
|
||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8")
|
||||
+ "&original_request_method=post", response.getRedirectedUrl());
|
||||
|
||||
// test the multiple query params
|
||||
ep.setIncludeOriginalParameters(true);
|
||||
@ -308,46 +310,42 @@ public class CaptchaEntryPointTests extends TestCase {
|
||||
request.addParameter("name1", "value2");
|
||||
response = new MockHttpServletResponse();
|
||||
ep.commence(request, response);
|
||||
assertEquals(
|
||||
"http://www.example.com:8888/hello?original_requestUrl="
|
||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8")
|
||||
+ "&original_request_method=post"
|
||||
+ "&original_request_parameters="
|
||||
+ URLEncoder.encode("name@@value;;name1@@value2", "UTF-8"),
|
||||
response.getRedirectedUrl());
|
||||
assertEquals("http://www.example.com:8888/hello?original_requestUrl="
|
||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8")
|
||||
+ "&original_request_method=post" + "&original_request_parameters="
|
||||
+ URLEncoder.encode("name__value;;name1__value2", "UTF-8"),
|
||||
response.getRedirectedUrl());
|
||||
|
||||
// test add parameter to captcha form url??
|
||||
|
||||
ep.setCaptchaFormUrl("/hello?toto=titi");
|
||||
response = new MockHttpServletResponse();
|
||||
ep.commence(request, response);
|
||||
assertEquals(
|
||||
"http://www.example.com:8888/hello?toto=titi&original_requestUrl="
|
||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8")
|
||||
+ "&original_request_method=post" + "&original_request_parameters="
|
||||
+ URLEncoder.encode("name@@value;;name1@@value2", "UTF-8"),
|
||||
response.getRedirectedUrl());
|
||||
"http://www.example.com:8888/hello?toto=titi&original_requestUrl="
|
||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8")
|
||||
+ "&original_request_method=post" + "&original_request_parameters="
|
||||
+ URLEncoder.encode("name__value;;name1__value2", "UTF-8"),
|
||||
response.getRedirectedUrl());
|
||||
|
||||
// with forcing!!!
|
||||
ep.setForceHttps(true);
|
||||
response = new MockHttpServletResponse();
|
||||
ep.commence(request, response);
|
||||
assertEquals(
|
||||
"https://www.example.com:1234/hello?toto=titi&original_requestUrl="
|
||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8") +
|
||||
"&original_request_method=post"
|
||||
+ "&original_request_parameters="
|
||||
+ URLEncoder.encode("name@@value;;name1@@value2", "UTF-8"),
|
||||
response.getRedirectedUrl());
|
||||
|
||||
"https://www.example.com:1234/hello?toto=titi&original_requestUrl="
|
||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8")
|
||||
+ "&original_request_method=post" + "&original_request_parameters="
|
||||
+ URLEncoder.encode("name__value;;name1__value2", "UTF-8"),
|
||||
response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
public void testOperationWithOutsideWebApp() throws Exception {
|
||||
CaptchaEntryPoint ep = new CaptchaEntryPoint();
|
||||
ep.setCaptchaFormUrl("https://www.jcaptcha.net/dotest/");
|
||||
|
||||
PortMapperImpl mapper = new PortMapperImpl();
|
||||
mapper.getTranslatedPortMappings().put(new Integer(8888),
|
||||
new Integer(1234));
|
||||
new Integer(1234));
|
||||
ep.setPortMapper(mapper);
|
||||
|
||||
ep.setPortResolver(new MockPortResolver(8888, 1234));
|
||||
@ -355,36 +353,32 @@ public class CaptchaEntryPointTests extends TestCase {
|
||||
ep.setOutsideWebApp(true);
|
||||
|
||||
ep.afterPropertiesSet();
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/some_path");
|
||||
request.setScheme("http");
|
||||
request.setServerName("www.example.com");
|
||||
request.setMethod("post");
|
||||
|
||||
// request.setContextPath("/bigWebApp");
|
||||
// TODO correct this when the getRequestUrl from mock works...
|
||||
|
||||
request.setServerPort(8888); // NB: Port we can't resolve
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
ep.afterPropertiesSet();
|
||||
ep.commence(request, response);
|
||||
assertEquals(
|
||||
"https://www.jcaptcha.net/dotest/?original_requestUrl="
|
||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8")
|
||||
+ "&original_request_method=post"
|
||||
,
|
||||
response.getRedirectedUrl());
|
||||
assertEquals("https://www.jcaptcha.net/dotest/?original_requestUrl="
|
||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8")
|
||||
+ "&original_request_method=post", response.getRedirectedUrl());
|
||||
|
||||
// test the query params
|
||||
request.addParameter("name", "value");
|
||||
response = new MockHttpServletResponse();
|
||||
ep.commence(request, response);
|
||||
assertEquals(
|
||||
"https://www.jcaptcha.net/dotest/?original_requestUrl="
|
||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8") +
|
||||
"&original_request_method=post",
|
||||
response.getRedirectedUrl());
|
||||
assertEquals("https://www.jcaptcha.net/dotest/?original_requestUrl="
|
||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8")
|
||||
+ "&original_request_method=post", response.getRedirectedUrl());
|
||||
|
||||
// test the multiple query params
|
||||
ep.setIncludeOriginalParameters(true);
|
||||
@ -392,39 +386,32 @@ public class CaptchaEntryPointTests extends TestCase {
|
||||
request.addParameter("name1", "value2");
|
||||
response = new MockHttpServletResponse();
|
||||
ep.commence(request, response);
|
||||
assertEquals(
|
||||
"https://www.jcaptcha.net/dotest/?original_requestUrl="
|
||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8")
|
||||
+ "&original_request_method=post"
|
||||
+ "&original_request_parameters="
|
||||
+ URLEncoder.encode("name@@value;;name1@@value2", "UTF-8"),
|
||||
response.getRedirectedUrl());
|
||||
assertEquals("https://www.jcaptcha.net/dotest/?original_requestUrl="
|
||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8")
|
||||
+ "&original_request_method=post" + "&original_request_parameters="
|
||||
+ URLEncoder.encode("name__value;;name1__value2", "UTF-8"),
|
||||
response.getRedirectedUrl());
|
||||
|
||||
// test add parameter to captcha form url??
|
||||
|
||||
ep.setCaptchaFormUrl("https://www.jcaptcha.net/dotest/?toto=titi");
|
||||
response = new MockHttpServletResponse();
|
||||
ep.commence(request, response);
|
||||
assertEquals(
|
||||
"https://www.jcaptcha.net/dotest/?toto=titi&original_requestUrl="
|
||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8") +
|
||||
"&original_request_method=post"
|
||||
+ "&original_request_parameters="
|
||||
+ URLEncoder.encode("name@@value;;name1@@value2", "UTF-8"),
|
||||
response.getRedirectedUrl());
|
||||
"https://www.jcaptcha.net/dotest/?toto=titi&original_requestUrl="
|
||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8")
|
||||
+ "&original_request_method=post" + "&original_request_parameters="
|
||||
+ URLEncoder.encode("name__value;;name1__value2", "UTF-8"),
|
||||
response.getRedirectedUrl());
|
||||
|
||||
// with forcing!!!
|
||||
ep.setForceHttps(true);
|
||||
response = new MockHttpServletResponse();
|
||||
ep.commence(request, response);
|
||||
assertEquals(
|
||||
"https://www.jcaptcha.net/dotest/?toto=titi&original_requestUrl="
|
||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8") +
|
||||
"&original_request_method=post"
|
||||
+ "&original_request_parameters="
|
||||
+ URLEncoder.encode("name@@value;;name1@@value2", "UTF-8"),
|
||||
response.getRedirectedUrl());
|
||||
|
||||
"https://www.jcaptcha.net/dotest/?toto=titi&original_requestUrl="
|
||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8")
|
||||
+ "&original_request_method=post" + "&original_request_parameters="
|
||||
+ URLEncoder.encode("name__value;;name1__value2", "UTF-8"),
|
||||
response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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,6 +17,7 @@ package net.sf.acegisecurity.captcha;
|
||||
|
||||
import net.sf.acegisecurity.context.SecurityContextImplTests;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link CaptchaSecurityContextImpl}.
|
||||
*
|
||||
@ -24,14 +25,46 @@ import net.sf.acegisecurity.context.SecurityContextImplTests;
|
||||
* @version $Id$
|
||||
*/
|
||||
public class CaptchaSecurityContextImplTests extends SecurityContextImplTests {
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void testDefaultValues() {
|
||||
CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
|
||||
assertEquals("should not be human", false, context.isHuman());
|
||||
assertEquals("should be 0", 0, context
|
||||
.getLastPassedCaptchaDateInMillis());
|
||||
assertEquals("should be 0", 0, context
|
||||
.getHumanRestrictedResourcesRequestsCount());
|
||||
assertEquals("should be 0", 0,
|
||||
context.getLastPassedCaptchaDateInMillis());
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user