Finalizing the validation, entry point and channel processor concerning captchas. Replacing the Thread.sleep() in captchaChannelProcessorTest to avoid the build break issue.

This commit is contained in:
Marc-Antoine Garrigue 2005-09-20 12:24:47 +00:00
parent 6f3e92e2e4
commit 60d3b6505b
11 changed files with 1447 additions and 1209 deletions

View File

@ -79,7 +79,7 @@ import org.springframework.util.Assert;
*
*
*
* <li>{@link #getRequiresHumanUntilMaxRequestsKeyword()} <br>
* <li>{@link #getRequiresHumanAfterMaxRequestsKeyword()} <br>
* default value = <code>REQUIRES_HUMAN_AFTER_MAX_MILLIS</code> <br>
* if detected, checks if :
*
@ -158,6 +158,9 @@ public class CaptchaChannelProcessor implements ChannelProcessor,
private String requiresHumanAfterMaxMillisKeyword = "REQUIRES_HUMAN_AFTER_MAX_MILLIS";
private String keywordPrefix = "";
private ChannelEntryPoint entryPoint;
private int maxRequestsBeforeReTest = -1;
@ -166,6 +169,14 @@ public class CaptchaChannelProcessor implements ChannelProcessor,
private long maxMillisBeforeReTest = -1;
public String getKeywordPrefix() {
return keywordPrefix;
}
public void setKeywordPrefix(String keywordPrefix) {
this.keywordPrefix = keywordPrefix;
}
public String getRequiresHumanAfterMaxMillisKeyword() {
return requiresHumanAfterMaxMillisKeyword;
}
@ -227,27 +238,20 @@ public class CaptchaChannelProcessor implements ChannelProcessor,
if ((invocation == null) || (config == null)) {
throw new IllegalArgumentException("Nulls cannot be provided");
}
CaptchaSecurityContext context = (CaptchaSecurityContext) SecurityContextHolder
CaptchaSecurityContext context = null;
context = (CaptchaSecurityContext) SecurityContextHolder
.getContext();
Iterator iter = config.getConfigAttributes();
boolean shouldRedirect = true;
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 = false;
} else {
// reset if already passed a constraint
if (!isContextValidForAttribute(context, attribute)) {
shouldRedirect = true;
// break at first unsatisfy contraint
break;
}
}
}
if (shouldRedirect) {
@ -270,8 +274,7 @@ public class CaptchaChannelProcessor implements ChannelProcessor,
if ((attribute != null) || (attribute.getAttribute() != null)) {
// test the REQUIRES_HUMAN_AFTER_MAX_REQUESTS keyword
if (attribute.getAttribute().equals(
getRequiresHumanAfterMaxRequestsKeyword())) {
if (isKeywordMaxRequest(attribute)) {
if (isContextValidConcerningHumanOrFirstTest(context)
&& isContextValidConcerningReTest(context)) {
valid = true;
@ -279,8 +282,7 @@ public class CaptchaChannelProcessor implements ChannelProcessor,
}
// test the REQUIRES_HUMAN_AFTER_MAX_MILLIS keyword
if (attribute.getAttribute().equals(
getRequiresHumanAfterMaxMillisKeyword())) {
if (isKeywordMillis(attribute)) {
if (isContextValidConcerningHumanOrFirstTest(context)
&& isContextValidConcerningMaxMillis(context)) {
valid = true;
@ -346,10 +348,7 @@ public class CaptchaChannelProcessor implements ChannelProcessor,
public boolean supports(ConfigAttribute attribute) {
if ((attribute != null)
&& (attribute.getAttribute() != null)
&& (attribute.getAttribute().equals(
getRequiresHumanAfterMaxRequestsKeyword()) || attribute
.getAttribute().equals(
getRequiresHumanAfterMaxMillisKeyword())
&& (isKeywordMaxRequest(attribute) || isKeywordMillis(attribute)
)) {
return true;
@ -358,4 +357,15 @@ public class CaptchaChannelProcessor implements ChannelProcessor,
}
}
private boolean isKeywordMillis(ConfigAttribute attribute) {
return attribute
.getAttribute().equals(
getKeywordPrefix()+getRequiresHumanAfterMaxMillisKeyword());
}
private boolean isKeywordMaxRequest(ConfigAttribute attribute) {
return attribute.getAttribute().equals(
getKeywordPrefix()+getRequiresHumanAfterMaxRequestsKeyword());
}
}

View File

@ -14,38 +14,54 @@
*/
package net.sf.acegisecurity.captcha;
import java.io.IOException;
import java.util.Enumeration;
import net.sf.acegisecurity.securechannel.ChannelEntryPoint;
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 javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.acegisecurity.securechannel.ChannelEntryPoint;
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;
/**
* 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/>
*
* This entry point allows internal OR external redirect : see
* {@link #setOutsideWebApp(boolean)}<br/>/ Original request can be added to
* the redirect path using a special parameter : see
* {@link #getOriginalRequestParameterName()} and
* {@link #setIncludeOriginalRequest()} <br/> <br/> Default values :<br/>
* forceHttps = false<br/> includesOriginalRequest = false<br/>
* originalRequestParameterName= "originalRequest"<br/> isOutsideWebApp=false<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/>
*
* @author marc antoine Garrigue
* @version $Id$
@ -68,22 +84,31 @@ public class CaptchaEntryPoint implements ChannelEntryPoint, InitializingBean {
private boolean forceHttps = false;
private String originalRequestParameterName = "originalRequest";
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 urlEncodingCharset = "UTF-8";
private boolean isOutsideWebApp = false;
private boolean includeOriginalRequest = false;
private boolean includeOriginalRequest = true;
private boolean includeOriginalParameters = false;
// ~ 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
*
* @param forceHttps
* 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
*/
public void setForceHttps(boolean forceHttps) {
this.forceHttps = forceHttps;
@ -94,14 +119,11 @@ public class CaptchaEntryPoint implements ChannelEntryPoint, InitializingBean {
}
/**
* 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
* 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 loginFormUrl) {
this.captchaFormUrl = loginFormUrl;
public void setCaptchaFormUrl(String captchaFormUrl) {
this.captchaFormUrl = captchaFormUrl;
}
/**
@ -127,54 +149,100 @@ 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 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.
*
* @param isOutsideWebApp
* 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 String getOriginalRequestParameterName() {
return originalRequestParameterName;
}
/**
* sets the parameter under which the original request url will be appended
* to the redirect url (only if {@link #isIncludeOriginalRequest()}==true).
*
* @param originalRequestParameterName
*/
public void setOriginalRequestParameterName(
String originalRequestParameterName) {
this.originalRequestParameterName = originalRequestParameterName;
}
public boolean isIncludeOriginalRequest() {
return includeOriginalRequest;
}
/**
* If set to true, the original request url will be appended to the redirect
* url using the {@link #getOriginalRequestParameterName()}.
*
* @param 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.notNull(portMapper, "portMapper must be specified");
Assert.notNull(portResolver, "portResolver must be specified");
URLEncoder.encode(" fzaef é& à ", urlEncodingCharset);
}
public void commence(ServletRequest request, ServletResponse response)
@ -191,14 +259,13 @@ public class CaptchaEntryPoint implements ChannelEntryPoint, InitializingBean {
if (includeOriginalRequest) {
includeOriginalRequest(redirectUrl, req);
}
// add post parameter? TODO?
// add post parameter? DONE!
if (logger.isDebugEnabled()) {
logger.debug("Redirecting to: " + redirectUrl);
}
((HttpServletResponse) response)
.sendRedirect(((HttpServletResponse) response)
.encodeRedirectURL(redirectUrl.toString()));
.sendRedirect(redirectUrl.toString());
}
private void includeOriginalRequest(StringBuffer redirectUrl,
@ -209,24 +276,48 @@ public class CaptchaEntryPoint implements ChannelEntryPoint, InitializingBean {
} else {
redirectUrl.append("?");
}
redirectUrl.append(originalRequestParameterName);
redirectUrl.append(originalRequestUrlParameterName);
redirectUrl.append("=");
redirectUrl.append(req.getRequestURL().toString());
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()) {
redirectUrl.append("?");
//qp.append("?");
while (parameters.hasMoreElements()) {
String name = parameters.nextElement().toString();
String value = req.getParameter(name);
redirectUrl.append(name);
redirectUrl.append("=");
redirectUrl.append(value);
qp.append(name);
qp.append(originalRequestParametersNameValueSeparator);
qp.append(value);
if (parameters.hasMoreElements()) {
redirectUrl.append("&");
qp.append(originalRequestParametersSeparator);
}
}
}
try {
redirectUrl.append(URLEncoder.encode(qp.toString(), urlEncodingCharset));
} catch (Exception e) {
logger.warn(e);
}
}
}

View File

@ -30,8 +30,6 @@ public interface CaptchaSecurityContext extends SecurityContext {
/**
* set human attribute, should called after captcha validation.
*
* @param human
*/
void setHuman();

View File

@ -1,3 +1,18 @@
/* 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 javax.servlet.ServletRequest;
@ -11,7 +26,9 @@ import javax.servlet.ServletRequest;
public interface CaptchaServiceProxy {
/**
* @return true if the request is validated by the back end captcha service.
* @param id the id token
* @param captchaResponse the user response
* @return true if the response is validated by the back end captcha service.
*/
boolean validateRequest(ServletRequest request);
boolean validateReponseForId(String id , Object captchaResponse);
}

View File

@ -15,33 +15,24 @@
package net.sf.acegisecurity.captcha;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
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 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/> <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/>
*
* @author marc antoine Garrigue
* @version $Id$
@ -50,15 +41,15 @@ public class CaptchaValidationProcessingFilter implements InitializingBean,
Filter {
// ~ Static fields/initializers
// =============================================
public static String CAPTCHA_VALIDATION_SECURITY_PARAMETER_KEY = "_captcha_parameter";
protected static final Log logger = LogFactory
.getLog(HttpSessionContextIntegrationFilter.class);
.getLog(CaptchaValidationProcessingFilter.class);
// ~ Instance fields
// ========================================================
private CaptchaServiceProxy captchaService;
private String captchaValidationParameter = "_captcha_parameter";
// ~ Methods
// ================================================================
@ -71,11 +62,24 @@ public class CaptchaValidationProcessingFilter implements InitializingBean,
this.captchaService = captchaService;
}
public String getCaptchaValidationParameter() {
return captchaValidationParameter;
}
public void setCaptchaValidationParameter(String captchaValidationParameter) {
this.captchaValidationParameter = captchaValidationParameter;
}
public void afterPropertiesSet() throws Exception {
if (this.captchaService == null) {
throw new IllegalArgumentException(
"CaptchaServiceProxy must be defined ");
}
if (this.captchaValidationParameter == null||"".equals(captchaValidationParameter)) {
throw new IllegalArgumentException(
"captchaValidationParameter must not be empty or null");
}
}
/**
@ -86,25 +90,39 @@ public class CaptchaValidationProcessingFilter implements InitializingBean,
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)) {
if ((request != null)
&& (request
.getParameter(CAPTCHA_VALIDATION_SECURITY_PARAMETER_KEY) != null)) {
logger.debug("captcha validation parameter not found, do nothing");
logger.debug("captcha validation parameter found");
// validate the request against CaptchaServiceProxy
boolean valid = false;
logger.debug("try to validate");
valid = this.captchaService.validateRequest(request);
//get session
HttpSession session = ((HttpServletRequest) request).getSession();
if (session != null) {
String id = session.getId();
valid = this.captchaService.validateReponseForId(id,
captcha_reponse);
logger.debug("captchaServiceProxy says : request is valid = "
+ valid);
if (valid) {
logger.debug("update the context");
((CaptchaSecurityContext) SecurityContextHolder.getContext())
.setHuman();
//logger.debug("retrieve original request from ")
}else{
logger.debug("captcha test failed");
}
}else{
logger.debug("no session found, user don't even ask a captcha challenge");
}
} else {
logger.debug("captcha validation parameter not found, do nothing");
}
@ -115,11 +133,9 @@ public class CaptchaValidationProcessingFilter implements InitializingBean,
/**
* Does nothing. We use IoC container lifecycle services instead.
*
* @param filterConfig
* ignored
* @param filterConfig ignored
*
* @throws ServletException
* ignored
* @throws ServletException ignored
*/
public void init(FilterConfig filterConfig) throws ServletException {
}

View File

@ -15,22 +15,21 @@
package net.sf.acegisecurity.captcha;
import java.io.IOException;
import javax.servlet.ServletException;
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$
*/
@ -48,6 +47,8 @@ public class CaptchaChannelProcessorTests extends TestCase {
CaptchaChannelProcessor processor = new CaptchaChannelProcessor();
CaptchaEntryPoint epoint = new CaptchaEntryPoint();
epoint.setCaptchaFormUrl("/jcaptcha.do");
epoint.setIncludeOriginalRequest(false);
processor.setEntryPoint(epoint);
MockHttpServletRequest request = new MockHttpServletRequest();
@ -98,6 +99,8 @@ public class CaptchaChannelProcessorTests extends TestCase {
CaptchaChannelProcessor processor = new CaptchaChannelProcessor();
CaptchaEntryPoint epoint = new CaptchaEntryPoint();
epoint.setCaptchaFormUrl("/jcaptcha.do");
epoint.setIncludeOriginalRequest(false);
processor.setEntryPoint(epoint);
MockHttpServletRequest request = new MockHttpServletRequest();
@ -149,6 +152,8 @@ public class CaptchaChannelProcessorTests extends TestCase {
CaptchaChannelProcessor processor = new CaptchaChannelProcessor();
CaptchaEntryPoint epoint = new CaptchaEntryPoint();
epoint.setCaptchaFormUrl("/jcaptcha.do");
epoint.setIncludeOriginalRequest(false);
processor.setEntryPoint(epoint);
MockHttpServletRequest request = new MockHttpServletRequest();
@ -249,16 +254,6 @@ public class CaptchaChannelProcessorTests extends TestCase {
assertTrue(true);
}
}
/*
// TODO: Re-enable these tests.
Commented out by Ben Alex on 19 Sep 05 as the Thread.sleep(100) approach to simulating
request age caused intermittent problems. An alternative approach should be used
instead, such as (a) modifying the CaptchaSecurityContextImpl (why not make a package
protected setLastPassedCaptchaDateInMillis) or (b) providing a package protected method
so that the unit test can modify the time being used by CaptchaChannelProcesor instead
of using System.currentTimeMillis().
public void testDecideMillis() throws Exception {
ConfigAttributeDefinition cad = new ConfigAttributeDefinition();
@ -272,6 +267,8 @@ public class CaptchaChannelProcessorTests extends TestCase {
CaptchaChannelProcessor processor = new CaptchaChannelProcessor();
CaptchaEntryPoint epoint = new CaptchaEntryPoint();
epoint.setCaptchaFormUrl("/jcaptcha.do");
epoint.setIncludeOriginalRequest(false);
processor.setEntryPoint(epoint);
MockHttpServletRequest request = new MockHttpServletRequest();
@ -311,7 +308,7 @@ public class CaptchaChannelProcessorTests extends TestCase {
response = decideWithNewResponse(cad, processor, request);
assertEquals(null, response.getRedirectedUrl());
Thread.sleep(100);
waitFor(100);
response = decideWithNewResponse(cad, processor, request);
assertEquals("http://localhost:8000/demo/jcaptcha.do", response
@ -327,7 +324,7 @@ public class CaptchaChannelProcessorTests extends TestCase {
response = decideWithNewResponse(cad, processor, request);
assertEquals(null, response.getRedirectedUrl());
Thread.sleep(100);
waitFor(100);
response = decideWithNewResponse(cad, processor, request);
assertEquals("http://localhost:8000/demo/jcaptcha.do", response
@ -342,7 +339,7 @@ public class CaptchaChannelProcessorTests extends TestCase {
response = decideWithNewResponse(cad, processor, request);
assertEquals(null, response.getRedirectedUrl());
Thread.sleep(100);
waitFor(100);
response = decideWithNewResponse(cad, processor, request);
assertEquals("http://localhost:8000/demo/jcaptcha.do", response
@ -363,6 +360,8 @@ public class CaptchaChannelProcessorTests extends TestCase {
CaptchaChannelProcessor processor = new CaptchaChannelProcessor();
CaptchaEntryPoint epoint = new CaptchaEntryPoint();
epoint.setCaptchaFormUrl("/jcaptcha.do");
epoint.setIncludeOriginalRequest(false);
processor.setEntryPoint(epoint);
MockHttpServletRequest request = new MockHttpServletRequest();
@ -403,7 +402,7 @@ public class CaptchaChannelProcessorTests extends TestCase {
response = decideWithNewResponse(cad, processor, request);
assertEquals(null, response.getRedirectedUrl());
Thread.sleep(100);
waitFor(100);
response = decideWithNewResponse(cad, processor, request);
assertEquals("http://localhost:8000/demo/jcaptcha.do", response
@ -436,7 +435,7 @@ public class CaptchaChannelProcessorTests extends TestCase {
response = decideWithNewResponse(cad, processor, request);
assertEquals(null, response.getRedirectedUrl());
Thread.sleep(100);
waitFor(100);
response = decideWithNewResponse(cad, processor, request);
assertEquals("http://localhost:8000/demo/jcaptcha.do", response
@ -446,7 +445,7 @@ public class CaptchaChannelProcessorTests extends TestCase {
assertEquals("http://localhost:8000/demo/jcaptcha.do", response
.getRedirectedUrl());
}
*/
public void testGettersSetters() {
CaptchaChannelProcessor processor = new CaptchaChannelProcessor();
assertEquals("REQUIRES_HUMAN_AFTER_MAX_MILLIS", processor
@ -543,4 +542,11 @@ public class CaptchaChannelProcessorTests extends TestCase {
assertFalse(processor.supports(new SecurityConfig("NOT_SUPPORTED")));
}
private void waitFor(int time){
long start=System.currentTimeMillis();
while(System.currentTimeMillis()<start+time){
}
return;
}
}

View File

@ -15,23 +15,21 @@
package net.sf.acegisecurity.captcha;
import java.util.HashMap;
import java.util.Map;
import junit.framework.TestCase;
import net.sf.acegisecurity.MockPortResolver;
import net.sf.acegisecurity.securechannel.RetryWithHttpEntryPoint;
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 RetryWithHttpEntryPoint}.
* Tests {@link CaptchaEntryPoint}.
*
* @author Ben Alex
* @version $Id: RetryWithHttpEntryPointTests.java,v 1.4 2005/04/11 01:07:02
* luke_t Exp $
* @author marc antoine Garrigue
* @version $Id$
*/
public class CaptchaEntryPointTests extends TestCase {
// ~ Methods
@ -96,13 +94,13 @@ public class CaptchaEntryPointTests extends TestCase {
assertTrue(ep.getPortMapper() != null);
assertTrue(ep.getPortResolver() != null);
assertEquals("originalRequest", ep.getOriginalRequestParameterName());
ep.setOriginalRequestParameterName("Z");
assertEquals("Z", ep.getOriginalRequestParameterName());
assertEquals("original_requestUrl", ep.getOriginalRequestUrlParameterName());
ep.setOriginalRequestUrlParameterName("Z");
assertEquals("Z", ep.getOriginalRequestUrlParameterName());
assertEquals(false, ep.isIncludeOriginalRequest());
ep.setIncludeOriginalRequest(true);
assertEquals(true, ep.isIncludeOriginalRequest());
ep.setIncludeOriginalRequest(false);
assertEquals(false, ep.isIncludeOriginalRequest());
assertEquals(false, ep.isOutsideWebApp());
ep.setOutsideWebApp(true);
@ -117,6 +115,7 @@ public class CaptchaEntryPointTests extends TestCase {
public void testHttpsOperationFromOriginalHttpUrl() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/some_path");
request.setScheme("http");
request.setServerName("www.example.com");
@ -126,6 +125,7 @@ public class CaptchaEntryPointTests extends TestCase {
MockHttpServletResponse response = new MockHttpServletResponse();
CaptchaEntryPoint ep = new CaptchaEntryPoint();
ep.setIncludeOriginalRequest(false);
ep.setCaptchaFormUrl("/hello");
ep.setPortMapper(new PortMapperImpl());
ep.setForceHttps(true);
@ -163,6 +163,8 @@ public class CaptchaEntryPointTests extends TestCase {
ep.setForceHttps(true);
ep.setPortMapper(portMapper);
ep.setPortResolver(new MockPortResolver(8888, 9999));
ep.setIncludeOriginalRequest(false);
ep.afterPropertiesSet();
ep.commence(request, response);
@ -172,6 +174,7 @@ public class CaptchaEntryPointTests extends TestCase {
public void testHttpsOperationFromOriginalHttpsUrl() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/some_path");
request.setScheme("https");
request.setServerName("www.example.com");
@ -181,6 +184,7 @@ public class CaptchaEntryPointTests extends TestCase {
MockHttpServletResponse response = new MockHttpServletResponse();
CaptchaEntryPoint ep = new CaptchaEntryPoint();
ep.setIncludeOriginalRequest(false);
ep.setCaptchaFormUrl("/hello");
ep.setPortMapper(new PortMapperImpl());
ep.setForceHttps(true);
@ -206,6 +210,8 @@ public class CaptchaEntryPointTests extends TestCase {
ep.setPortMapper(new PortMapperImpl());
ep.setPortResolver(new MockPortResolver(80, 443));
ep.afterPropertiesSet();
ep.setIncludeOriginalRequest(false);
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/some_path");
@ -230,6 +236,8 @@ public class CaptchaEntryPointTests extends TestCase {
ep.setPortMapper(new PortMapperImpl());
ep.setPortResolver(new MockPortResolver(8888, 1234));
ep.setForceHttps(true);
ep.setIncludeOriginalRequest(false);
ep.afterPropertiesSet();
MockHttpServletRequest request = new MockHttpServletRequest();
@ -264,6 +272,7 @@ public class CaptchaEntryPointTests extends TestCase {
ep.afterPropertiesSet();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("post");
request.setRequestURI("/some_path");
request.setScheme("http");
request.setServerName("www.example.com");
@ -277,7 +286,9 @@ public class CaptchaEntryPointTests extends TestCase {
ep.afterPropertiesSet();
ep.commence(request, response);
assertEquals(
"http://www.example.com:8888/hello?originalRequest=http://www.example.com:8888/some_path",
"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
@ -285,16 +296,24 @@ public class CaptchaEntryPointTests extends TestCase {
response = new MockHttpServletResponse();
ep.commence(request, response);
assertEquals(
"http://www.example.com:8888/hello?originalRequest=http://www.example.com:8888/some_path?name=value",
"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);
request.addParameter("name", "value");
request.addParameter("name1", "value2");
response = new MockHttpServletResponse();
ep.commence(request, response);
assertEquals(
"http://www.example.com:8888/hello?originalRequest=http://www.example.com:8888/some_path?name=value&name1=value2",
"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??
@ -303,7 +322,10 @@ public class CaptchaEntryPointTests extends TestCase {
response = new MockHttpServletResponse();
ep.commence(request, response);
assertEquals(
"http://www.example.com:8888/hello?toto=titi&originalRequest=http://www.example.com:8888/some_path?name=value&name1=value2",
"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!!!
@ -311,7 +333,11 @@ public class CaptchaEntryPointTests extends TestCase {
response = new MockHttpServletResponse();
ep.commence(request, response);
assertEquals(
"https://www.example.com:1234/hello?toto=titi&originalRequest=http://www.example.com:8888/some_path?name=value&name1=value2",
"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());
}
@ -333,6 +359,7 @@ public class CaptchaEntryPointTests extends TestCase {
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...
@ -343,7 +370,10 @@ public class CaptchaEntryPointTests extends TestCase {
ep.afterPropertiesSet();
ep.commence(request, response);
assertEquals(
"https://www.jcaptcha.net/dotest/?originalRequest=http://www.example.com:8888/some_path",
"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
@ -351,16 +381,23 @@ public class CaptchaEntryPointTests extends TestCase {
response = new MockHttpServletResponse();
ep.commence(request, response);
assertEquals(
"https://www.jcaptcha.net/dotest/?originalRequest=http://www.example.com:8888/some_path?name=value",
"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);
request.addParameter("name", "value");
request.addParameter("name1", "value2");
response = new MockHttpServletResponse();
ep.commence(request, response);
assertEquals(
"https://www.jcaptcha.net/dotest/?originalRequest=http://www.example.com:8888/some_path?name=value&name1=value2",
"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??
@ -369,7 +406,11 @@ public class CaptchaEntryPointTests extends TestCase {
response = new MockHttpServletResponse();
ep.commence(request, response);
assertEquals(
"https://www.jcaptcha.net/dotest/?toto=titi&originalRequest=http://www.example.com:8888/some_path?name=value&name1=value2",
"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!!!
@ -377,7 +418,11 @@ public class CaptchaEntryPointTests extends TestCase {
response = new MockHttpServletResponse();
ep.commence(request, response);
assertEquals(
"https://www.jcaptcha.net/dotest/?toto=titi&originalRequest=http://www.example.com:8888/some_path?name=value&name1=value2",
"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());
}

View File

@ -1,7 +1,28 @@
/* 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 net.sf.acegisecurity.context.SecurityContextImplTests;
/**
* Tests {@link CaptchaSecurityContextImpl}.
*
* @author marc antoine Garrigue
* @version $Id$
*/
public class CaptchaSecurityContextImplTests extends SecurityContextImplTests {
public void testDefaultValues() {

View File

@ -1,11 +1,31 @@
/* 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.context.SecurityContextHolder;
import net.sf.acegisecurity.util.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
/**
* Tests {@link CaptchaValidationProcessingFilter}.
*
* @author marc antoine Garrigue
* @version $Id$
*/
public class CaptchaValidationProcessingFilterTests extends TestCase {
/*
@ -21,8 +41,19 @@ public class CaptchaValidationProcessingFilterTests extends TestCase {
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()));
}
}
@ -60,12 +91,13 @@ public class CaptchaValidationProcessingFilterTests extends TestCase {
SecurityContextHolder.setContext(context);
MockHttpServletRequest request = new MockHttpServletRequest();
request
.addParameter(
CaptchaValidationProcessingFilter.CAPTCHA_VALIDATION_SECURITY_PARAMETER_KEY,
"");
CaptchaValidationProcessingFilter filter = new CaptchaValidationProcessingFilter();
request
.addParameter(
filter.getCaptchaValidationParameter(),
"");
MockCaptchaServiceProxy service = new MockCaptchaServiceProxy();
MockFilterChain chain = new MockFilterChain(true);
filter.setCaptchaService(service);

View File

@ -15,15 +15,17 @@
package net.sf.acegisecurity.captcha;
import javax.servlet.ServletRequest;
/**
* @author marc antoine Garrigue
* @version $Id$
*/
public class MockCaptchaServiceProxy implements CaptchaServiceProxy {
public boolean valid = false;
public boolean hasBeenCalled = false;
public boolean validateRequest(ServletRequest request) {
public boolean validateReponseForId(String id, Object response) {
hasBeenCalled = true;
return valid;