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> * default value = <code>REQUIRES_HUMAN_AFTER_MAX_MILLIS</code> <br>
* if detected, checks if : * if detected, checks if :
* *
@ -138,7 +138,7 @@ import org.springframework.util.Assert;
* and the REQUIRES_HUMAN_AFTER_MAX_REQUESTS keywords <br> * and the REQUIRES_HUMAN_AFTER_MAX_REQUESTS keywords <br>
* with a maxRequestsBeforeReTest=20 <br> * with a maxRequestsBeforeReTest=20 <br>
* and a maxMillisBeforeReTest=3600000 <br> * and a maxMillisBeforeReTest=3600000 <br>
* and amaxRequestsBeforeFirstTest=1000</li> * and a maxRequestsBeforeFirstTest=1000</li>
* *
* </ul> * </ul>
* *
@ -158,7 +158,10 @@ public class CaptchaChannelProcessor implements ChannelProcessor,
private String requiresHumanAfterMaxMillisKeyword = "REQUIRES_HUMAN_AFTER_MAX_MILLIS"; private String requiresHumanAfterMaxMillisKeyword = "REQUIRES_HUMAN_AFTER_MAX_MILLIS";
private ChannelEntryPoint entryPoint; private String keywordPrefix = "";
private ChannelEntryPoint entryPoint;
private int maxRequestsBeforeReTest = -1; private int maxRequestsBeforeReTest = -1;
@ -166,7 +169,15 @@ public class CaptchaChannelProcessor implements ChannelProcessor,
private long maxMillisBeforeReTest = -1; private long maxMillisBeforeReTest = -1;
public String getRequiresHumanAfterMaxMillisKeyword() { public String getKeywordPrefix() {
return keywordPrefix;
}
public void setKeywordPrefix(String keywordPrefix) {
this.keywordPrefix = keywordPrefix;
}
public String getRequiresHumanAfterMaxMillisKeyword() {
return requiresHumanAfterMaxMillisKeyword; return requiresHumanAfterMaxMillisKeyword;
} }
@ -227,28 +238,21 @@ public class CaptchaChannelProcessor implements ChannelProcessor,
if ((invocation == null) || (config == null)) { if ((invocation == null) || (config == null)) {
throw new IllegalArgumentException("Nulls cannot be provided"); throw new IllegalArgumentException("Nulls cannot be provided");
} }
CaptchaSecurityContext context = (CaptchaSecurityContext) SecurityContextHolder CaptchaSecurityContext context = null;
.getContext(); context = (CaptchaSecurityContext) SecurityContextHolder
.getContext();
Iterator iter = config.getConfigAttributes(); Iterator iter = config.getConfigAttributes();
boolean shouldRedirect = true; boolean shouldRedirect = false;
while (iter.hasNext()) { while (iter.hasNext()) {
ConfigAttribute attribute = (ConfigAttribute) iter.next(); ConfigAttribute attribute = (ConfigAttribute) iter.next();
if (supports(attribute)) { if (supports(attribute)) {
logger.debug("supports this attribute : " + attribute); logger.debug("supports this attribute : " + attribute);
if (isContextValidForAttribute(context, attribute)) { if (!isContextValidForAttribute(context, attribute)) {
shouldRedirect = false;
} else {
// reset if already passed a constraint
shouldRedirect = true; shouldRedirect = true;
// break at first unsatisfy contraint }
break; }
}
}
} }
if (shouldRedirect) { if (shouldRedirect) {
logger logger
@ -270,8 +274,7 @@ public class CaptchaChannelProcessor implements ChannelProcessor,
if ((attribute != null) || (attribute.getAttribute() != null)) { if ((attribute != null) || (attribute.getAttribute() != null)) {
// test the REQUIRES_HUMAN_AFTER_MAX_REQUESTS keyword // test the REQUIRES_HUMAN_AFTER_MAX_REQUESTS keyword
if (attribute.getAttribute().equals( if (isKeywordMaxRequest(attribute)) {
getRequiresHumanAfterMaxRequestsKeyword())) {
if (isContextValidConcerningHumanOrFirstTest(context) if (isContextValidConcerningHumanOrFirstTest(context)
&& isContextValidConcerningReTest(context)) { && isContextValidConcerningReTest(context)) {
valid = true; valid = true;
@ -279,8 +282,7 @@ public class CaptchaChannelProcessor implements ChannelProcessor,
} }
// test the REQUIRES_HUMAN_AFTER_MAX_MILLIS keyword // test the REQUIRES_HUMAN_AFTER_MAX_MILLIS keyword
if (attribute.getAttribute().equals( if (isKeywordMillis(attribute)) {
getRequiresHumanAfterMaxMillisKeyword())) {
if (isContextValidConcerningHumanOrFirstTest(context) if (isContextValidConcerningHumanOrFirstTest(context)
&& isContextValidConcerningMaxMillis(context)) { && isContextValidConcerningMaxMillis(context)) {
valid = true; valid = true;
@ -346,10 +348,7 @@ public class CaptchaChannelProcessor implements ChannelProcessor,
public boolean supports(ConfigAttribute attribute) { public boolean supports(ConfigAttribute attribute) {
if ((attribute != null) if ((attribute != null)
&& (attribute.getAttribute() != null) && (attribute.getAttribute() != null)
&& (attribute.getAttribute().equals( && (isKeywordMaxRequest(attribute) || isKeywordMillis(attribute)
getRequiresHumanAfterMaxRequestsKeyword()) || attribute
.getAttribute().equals(
getRequiresHumanAfterMaxMillisKeyword())
)) { )) {
return true; 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,274 +14,365 @@
*/ */
package net.sf.acegisecurity.captcha; package net.sf.acegisecurity.captcha;
import java.io.IOException; import net.sf.acegisecurity.securechannel.ChannelEntryPoint;
import java.util.Enumeration; 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.ServletException;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import net.sf.acegisecurity.securechannel.ChannelEntryPoint; import java.io.UnsupportedEncodingException;
import net.sf.acegisecurity.util.PortMapper; import java.net.URLEncoder;
import net.sf.acegisecurity.util.PortMapperImpl; import java.util.Enumeration;
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;
/** /**
* The captcha entry point : redirect to the captcha test page. <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/> * This entry point can force the use of SSL : see {@link #getForceHttps()}<br/>
* * <p/>
* This entry point allows internal OR external redirect : see * This entry point allows internal OR external redirect : see {@link #setOutsideWebApp(boolean)}<br/>/ Original request
* {@link #setOutsideWebApp(boolean)}<br/>/ Original request can be added to * can be added to the redirect path using a custom translation : see {@link #setIncludeOriginalRequest(boolean)} <br/>
* the redirect path using a special parameter : see * Original request is translated using URLEncoding and the following translation mapping in the redirect url : <ul>
* {@link #getOriginalRequestParameterName()} and * <li>original url => {@link #getOriginalRequestUrlParameterName()}</li> <li> If {@link
* {@link #setIncludeOriginalRequest()} <br/> <br/> Default values :<br/> * #isIncludeOriginalParameters()}</li> <li>original method => {@link #getOriginalRequestMethodParameterName()} </li>
* forceHttps = false<br/> includesOriginalRequest = false<br/> * <li>original parameters => {@link #getOriginalRequestParametersParameterName()} </li> <li>The orinial parameters
* originalRequestParameterName= "originalRequest"<br/> isOutsideWebApp=false<br/> * 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 * @author marc antoine Garrigue
* @version $Id$ * @version $Id$
*/ */
public class CaptchaEntryPoint implements ChannelEntryPoint, InitializingBean { public class CaptchaEntryPoint implements ChannelEntryPoint, InitializingBean {
// ~ Static fields/initializers // ~ Static fields/initializers
// ============================================= // =============================================
private static final Log logger = LogFactory private static final Log logger = LogFactory
.getLog(CaptchaEntryPoint.class); .getLog(CaptchaEntryPoint.class);
// ~ Instance fields // ~ Instance fields
// ======================================================== // ========================================================
private PortMapper portMapper = new PortMapperImpl(); private PortMapper portMapper = new PortMapperImpl();
private PortResolver portResolver = new PortResolverImpl(); private PortResolver portResolver = new PortResolverImpl();
private String captchaFormUrl; private String captchaFormUrl;
private boolean forceHttps = false; private boolean forceHttps = false;
private String originalRequestParameterName = "originalRequest"; private String originalRequestUrlParameterName = "original_requestUrl";
private boolean isOutsideWebApp = false; private String originalRequestParametersParameterName = "original_request_parameters";
private boolean includeOriginalRequest = false; private String originalRequestParametersNameValueSeparator = "@@";
// ~ Methods private String originalRequestParametersSeparator = ";;";
// ================================================================
/** private String originalRequestMethodParameterName = "original_request_method";
* 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;
}
public boolean getForceHttps() { private String urlEncodingCharset = "UTF-8";
return forceHttps;
}
/** private boolean isOutsideWebApp = 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 loginFormUrl) {
this.captchaFormUrl = loginFormUrl;
}
/** private boolean includeOriginalRequest = true;
* @return the captcha test page to redirect to.
*/
public String getCaptchaFormUrl() {
return captchaFormUrl;
}
public void setPortMapper(PortMapper portMapper) { private boolean includeOriginalParameters = false;
this.portMapper = portMapper;
}
public PortMapper getPortMapper() { // ~ Methods
return portMapper; // ================================================================
}
public void setPortResolver(PortResolver portResolver) { /**
this.portResolver = portResolver; * 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;
}
public PortResolver getPortResolver() { public boolean getForceHttps() {
return portResolver; return forceHttps;
} }
public boolean isOutsideWebApp() { /**
return isOutsideWebApp; * 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;
}
/** /**
* if set to true, the {@link #commence(ServletRequest, ServletResponse)} * @return the captcha test page to redirect to.
* method uses the {@link #getCaptchaFormUrl()} as a complete URL, else it */
* as a 'inside WebApp' path. public String getCaptchaFormUrl() {
* return captchaFormUrl;
* @param isOutsideWebApp }
*/
public void setOutsideWebApp(boolean isOutsideWebApp) {
this.isOutsideWebApp = isOutsideWebApp;
}
public String getOriginalRequestParameterName() { public void setPortMapper(PortMapper portMapper) {
return originalRequestParameterName; this.portMapper = portMapper;
} }
/** public PortMapper getPortMapper() {
* sets the parameter under which the original request url will be appended return portMapper;
* to the redirect url (only if {@link #isIncludeOriginalRequest()}==true). }
*
* @param originalRequestParameterName
*/
public void setOriginalRequestParameterName(
String originalRequestParameterName) {
this.originalRequestParameterName = originalRequestParameterName;
}
public boolean isIncludeOriginalRequest() { public void setPortResolver(PortResolver portResolver) {
return includeOriginalRequest; this.portResolver = portResolver;
} }
/** public PortResolver getPortResolver() {
* If set to true, the original request url will be appended to the redirect return portResolver;
* url using the {@link #getOriginalRequestParameterName()}. }
*
* @param includeOriginalRequest
*/
public void setIncludeOriginalRequest(boolean includeOriginalRequest) {
this.includeOriginalRequest = includeOriginalRequest;
}
public void afterPropertiesSet() throws Exception {
Assert.hasLength(captchaFormUrl, "captchaFormUrl must be specified");
Assert.notNull(portMapper, "portMapper must be specified");
Assert.notNull(portResolver, "portResolver must be specified");
}
public void commence(ServletRequest request, ServletResponse response) public boolean isOutsideWebApp() {
throws IOException, ServletException { return isOutsideWebApp;
StringBuffer redirectUrl = new StringBuffer(); }
HttpServletRequest req = (HttpServletRequest) request;
if (isOutsideWebApp) {
redirectUrl = redirectUrl.append(captchaFormUrl);
} else {
buildInternalRedirect(redirectUrl, req);
}
if (includeOriginalRequest) { public String getOriginalRequestUrlParameterName() {
includeOriginalRequest(redirectUrl, req); return originalRequestUrlParameterName;
} }
// add post parameter? TODO?
if (logger.isDebugEnabled()) {
logger.debug("Redirecting to: " + redirectUrl);
}
((HttpServletResponse) response) public void setOriginalRequestUrlParameterName(String originalRequestUrlParameterName) {
.sendRedirect(((HttpServletResponse) response) this.originalRequestUrlParameterName = originalRequestUrlParameterName;
.encodeRedirectURL(redirectUrl.toString())); }
}
private void includeOriginalRequest(StringBuffer redirectUrl, public String getOriginalRequestParametersParameterName() {
HttpServletRequest req) { return originalRequestParametersParameterName;
// add original request to the url }
if (redirectUrl.indexOf("?") >= 0) {
redirectUrl.append("&");
} else {
redirectUrl.append("?");
}
redirectUrl.append(originalRequestParameterName);
redirectUrl.append("=");
redirectUrl.append(req.getRequestURL().toString());
// append query params
Enumeration parameters = req.getParameterNames();
if (parameters != null && parameters.hasMoreElements()) {
redirectUrl.append("?");
while (parameters.hasMoreElements()) {
String name = parameters.nextElement().toString();
String value = req.getParameter(name);
redirectUrl.append(name);
redirectUrl.append("=");
redirectUrl.append(value);
if (parameters.hasMoreElements()) {
redirectUrl.append("&");
}
}
}
} public void setOriginalRequestParametersParameterName(String originalRequestParametersParameterName) {
this.originalRequestParametersParameterName = originalRequestParametersParameterName;
}
private void buildInternalRedirect(StringBuffer redirectUrl, public String getOriginalRequestParametersNameValueSeparator() {
HttpServletRequest req) { return originalRequestParametersNameValueSeparator;
// construct it }
StringBuffer simpleRedirect = new StringBuffer();
String scheme = req.getScheme(); public void setOriginalRequestParametersNameValueSeparator(String originalRequestParametersNameValueSeparator) {
String serverName = req.getServerName(); this.originalRequestParametersNameValueSeparator = originalRequestParametersNameValueSeparator;
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;
}
simpleRedirect.append(scheme); public String getOriginalRequestParametersSeparator() {
simpleRedirect.append("://"); return originalRequestParametersSeparator;
simpleRedirect.append(serverName); }
if (includePort) {
simpleRedirect.append(":");
simpleRedirect.append(serverPort);
}
simpleRedirect.append(contextPath);
simpleRedirect.append(captchaFormUrl);
if (forceHttps && req.getScheme().equals("http")) { public void setOriginalRequestParametersSeparator(String originalRequestParametersSeparator) {
Integer httpPort = new Integer(portResolver.getServerPort(req)); this.originalRequestParametersSeparator = originalRequestParametersSeparator;
Integer httpsPort = (Integer) portMapper.lookupHttpsPort(httpPort); }
if (httpsPort != null) { public String getOriginalRequestMethodParameterName() {
if (httpsPort.intValue() == 443) { return originalRequestMethodParameterName;
includePort = false; }
} else {
includePort = true;
}
redirectUrl.append("https://"); public void setOriginalRequestMethodParameterName(String originalRequestMethodParameterName) {
redirectUrl.append(serverName); this.originalRequestMethodParameterName = originalRequestMethodParameterName;
if (includePort) { }
redirectUrl.append(":");
redirectUrl.append(httpsPort); public String getUrlEncodingCharset() {
} return urlEncodingCharset;
redirectUrl.append(contextPath); }
redirectUrl.append(captchaFormUrl);
} else { public void setUrlEncodingCharset(String urlEncodingCharset) {
redirectUrl.append(simpleRedirect); this.urlEncodingCharset = urlEncodingCharset;
} }
} else {
redirectUrl.append(simpleRedirect); /**
} * 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.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 {
StringBuffer redirectUrl = new StringBuffer();
HttpServletRequest req = (HttpServletRequest) request;
if (isOutsideWebApp) {
redirectUrl = redirectUrl.append(captchaFormUrl);
} else {
buildInternalRedirect(redirectUrl, req);
}
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);
}
}
}
private void buildInternalRedirect(StringBuffer redirectUrl,
HttpServletRequest req) {
// construct it
StringBuffer simpleRedirect = new StringBuffer();
String scheme = req.getScheme();
String serverName = req.getServerName();
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;
}
simpleRedirect.append(scheme);
simpleRedirect.append("://");
simpleRedirect.append(serverName);
if (includePort) {
simpleRedirect.append(":");
simpleRedirect.append(serverPort);
}
simpleRedirect.append(contextPath);
simpleRedirect.append(captchaFormUrl);
if (forceHttps && req.getScheme().equals("http")) {
Integer httpPort = new Integer(portResolver.getServerPort(req));
Integer httpsPort = (Integer) portMapper.lookupHttpsPort(httpPort);
if (httpsPort != null) {
if (httpsPort.intValue() == 443) {
includePort = false;
} else {
includePort = true;
}
redirectUrl.append("https://");
redirectUrl.append(serverName);
if (includePort) {
redirectUrl.append(":");
redirectUrl.append(httpsPort);
}
redirectUrl.append(contextPath);
redirectUrl.append(captchaFormUrl);
} else {
redirectUrl.append(simpleRedirect);
}
} else {
redirectUrl.append(simpleRedirect);
}
}
} }

View File

@ -30,13 +30,11 @@ public interface CaptchaSecurityContext extends SecurityContext {
/** /**
* set human attribute, should called after captcha validation. * set human attribute, should called after captcha validation.
*
* @param human
*/ */
void setHuman(); void setHuman();
/** /**
* *
* @return number of human restricted resources requests since the last * @return number of human restricted resources requests since the last
* passed captcha. * passed captcha.
*/ */

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; package net.sf.acegisecurity.captcha;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
@ -11,7 +26,9 @@ import javax.servlet.ServletRequest;
public interface CaptchaServiceProxy { 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,112 +15,128 @@
package net.sf.acegisecurity.captcha; 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.HttpSessionContextIntegrationFilter;
import net.sf.acegisecurity.context.SecurityContextHolder; import net.sf.acegisecurity.context.SecurityContextHolder;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean; 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 * Filter for web integration of the {@link CaptchaServiceProxy}. <br/> It basically intercept calls containing the
* basically intercept calls containing the specific validation parameter, use * specific validation parameter, use the {@link CaptchaServiceProxy} to validate the request, and update the {@link
* the {@link CaptchaServiceProxy} to validate the request, and update the * CaptchaSecurityContext} if the request passed the validation. <br/> <br/> This Filter should be placed after the
* {@link CaptchaSecurityContext} if the request passed the validation. <br/> * ContextIntegration filter and before the {@link CaptchaChannelProcessor} filter in the filter stack in order to
* <br/> This Filter should be placed after the ContextIntegration filter and * update the {@link CaptchaSecurityContext} before the humanity verification routine occurs. <br/> <br/> This filter
* before the {@link CaptchaChannelProcessor} filter in the filter stack in * should only be used in conjunction with the {@link CaptchaSecurityContext} <br/> <br/>
* 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 * @author marc antoine Garrigue
* @version $Id$ * @version $Id$
*/ */
public class CaptchaValidationProcessingFilter implements InitializingBean, public class CaptchaValidationProcessingFilter implements InitializingBean,
Filter { Filter {
// ~ Static fields/initializers // ~ Static fields/initializers
// ============================================= // =============================================
public static String CAPTCHA_VALIDATION_SECURITY_PARAMETER_KEY = "_captcha_parameter"; protected static final Log logger = LogFactory
.getLog(CaptchaValidationProcessingFilter.class);
protected static final Log logger = LogFactory // ~ Instance fields
.getLog(HttpSessionContextIntegrationFilter.class); // ========================================================
// ~ Instance fields private CaptchaServiceProxy captchaService;
// ======================================================== private String captchaValidationParameter = "_captcha_parameter";
private CaptchaServiceProxy captchaService;
// ~ Methods // ~ Methods
// ================================================================ // ================================================================
public CaptchaServiceProxy getCaptchaService() { public CaptchaServiceProxy getCaptchaService() {
return captchaService; return captchaService;
} }
public void setCaptchaService(CaptchaServiceProxy captchaService) { public void setCaptchaService(CaptchaServiceProxy captchaService) {
this.captchaService = captchaService; this.captchaService = captchaService;
} }
public void afterPropertiesSet() throws Exception {
if (this.captchaService == null) {
throw new IllegalArgumentException(
"CaptchaServiceProxy must be defined ");
}
}
/** public String getCaptchaValidationParameter() {
* Does nothing. We use IoC container lifecycle services instead. return captchaValidationParameter;
*/ }
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response, public void setCaptchaValidationParameter(String captchaValidationParameter) {
FilterChain chain) throws IOException, ServletException { this.captchaValidationParameter = captchaValidationParameter;
}
if ((request != null) public void afterPropertiesSet() throws Exception {
&& (request if (this.captchaService == null) {
.getParameter(CAPTCHA_VALIDATION_SECURITY_PARAMETER_KEY) != null)) { throw new IllegalArgumentException(
logger.debug("captcha validation parameter not found, do nothing"); "CaptchaServiceProxy must be defined ");
// validate the request against CaptchaServiceProxy }
boolean valid = false; if (this.captchaValidationParameter == null||"".equals(captchaValidationParameter)) {
throw new IllegalArgumentException(
"captchaValidationParameter must not be empty or null");
}
}
logger.debug("try to validate"); /**
valid = this.captchaService.validateRequest(request); * Does nothing. We use IoC container lifecycle services instead.
logger.debug("captchaServiceProxy says : request is valid =" */
+ valid); public void destroy() {
if (valid) { }
logger.debug("update the context");
((CaptchaSecurityContext) SecurityContextHolder.getContext())
.setHuman();
} 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)) {
} else { logger.debug("captcha validation parameter found");
logger.debug("captcha validation parameter not found, do nothing"); // validate the request against CaptchaServiceProxy
} boolean valid = false;
logger.debug("chain...");
chain.doFilter(request, response);
}
/** logger.debug("try to validate");
* Does nothing. We use IoC container lifecycle services instead.
* //get session
* @param filterConfig HttpSession session = ((HttpServletRequest) request).getSession();
* ignored if (session != null) {
*
* @throws ServletException String id = session.getId();
* ignored valid = this.captchaService.validateReponseForId(id,
*/ captcha_reponse);
public void init(FilterConfig filterConfig) throws ServletException { 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");
}
logger.debug("chain ...");
chain.doFilter(request, response);
}
/**
* Does nothing. We use IoC container lifecycle services instead.
*
* @param filterConfig ignored
*
* @throws ServletException ignored
*/
public void init(FilterConfig filterConfig) throws ServletException {
}
} }

View File

@ -119,7 +119,7 @@ public class HttpSessionEventPublisher implements HttpSessionListener,
} }
ApplicationContext getContext() { ApplicationContext getContext() {
Assert.notNull(context, "setContext(...) never called, ApplicationContext must not be null"); Assert.notNull(context, "setContext(...) never called, ApplicationContext must not be null");
return context; return context;
} }
} }

View File

@ -15,532 +15,538 @@
package net.sf.acegisecurity.captcha; package net.sf.acegisecurity.captcha;
import java.io.IOException;
import javax.servlet.ServletException;
import junit.framework.TestCase; import junit.framework.TestCase;
import net.sf.acegisecurity.ConfigAttributeDefinition; import net.sf.acegisecurity.ConfigAttributeDefinition;
import net.sf.acegisecurity.MockFilterChain; import net.sf.acegisecurity.MockFilterChain;
import net.sf.acegisecurity.SecurityConfig; import net.sf.acegisecurity.SecurityConfig;
import net.sf.acegisecurity.context.SecurityContextHolder; import net.sf.acegisecurity.context.SecurityContextHolder;
import net.sf.acegisecurity.intercept.web.FilterInvocation; import net.sf.acegisecurity.intercept.web.FilterInvocation;
import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockHttpServletResponse;
/** import javax.servlet.ServletException;
* Tests {@link CaptchaChannelProcessor} import java.io.IOException;
/**
* Tests {@link CaptchaChannelProcessor}
*
* @author marc antoine Garrigue * @author marc antoine Garrigue
* @version $Id$ * @version $Id$
*/ */
public class CaptchaChannelProcessorTests extends TestCase { public class CaptchaChannelProcessorTests extends TestCase {
public void testDecideRequestsFirstTestRequests() throws Exception { public void testDecideRequestsFirstTestRequests() throws Exception {
ConfigAttributeDefinition cad = new ConfigAttributeDefinition(); ConfigAttributeDefinition cad = new ConfigAttributeDefinition();
cad.addConfigAttribute(new SecurityConfig("SOME_IGNORED_ATTRIBUTE")); cad.addConfigAttribute(new SecurityConfig("SOME_IGNORED_ATTRIBUTE"));
cad.addConfigAttribute(new SecurityConfig( cad.addConfigAttribute(new SecurityConfig(
"REQUIRES_HUMAN_AFTER_MAX_REQUESTS")); "REQUIRES_HUMAN_AFTER_MAX_REQUESTS"));
CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
SecurityContextHolder.setContext(context);
CaptchaChannelProcessor processor = new CaptchaChannelProcessor();
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(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); CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
assertEquals(null, response.getRedirectedUrl()); SecurityContextHolder.setContext(context);
response = decideWithNewResponse(cad, processor, request);
assertEquals("http://localhost:8000/demo/jcaptcha.do", response
.getRedirectedUrl());
}
public void testDecideRequestsFirstTestMillis() throws Exception { CaptchaChannelProcessor processor = new CaptchaChannelProcessor();
ConfigAttributeDefinition cad = new ConfigAttributeDefinition(); CaptchaEntryPoint epoint = new CaptchaEntryPoint();
cad.addConfigAttribute(new SecurityConfig("SOME_IGNORED_ATTRIBUTE")); epoint.setCaptchaFormUrl("/jcaptcha.do");
cad.addConfigAttribute(new SecurityConfig( epoint.setIncludeOriginalRequest(false);
"REQUIRES_HUMAN_AFTER_MAX_MILLIS"));
CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); processor.setEntryPoint(epoint);
SecurityContextHolder.setContext(context);
CaptchaChannelProcessor processor = new CaptchaChannelProcessor(); MockHttpServletRequest request = new MockHttpServletRequest();
CaptchaEntryPoint epoint = new CaptchaEntryPoint(); request.setQueryString("info=true");
epoint.setCaptchaFormUrl("/jcaptcha.do"); request.setServerName("localhost");
processor.setEntryPoint(epoint); request.setContextPath("/demo");
request.setServletPath("/restricted");
request.setScheme("http");
request.setServerPort(8000);
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse();
request.setQueryString("info=true"); MockFilterChain chain = new MockFilterChain();
request.setServerName("localhost"); FilterInvocation fi = new FilterInvocation(request, response, chain);
request.setContextPath("/demo");
request.setServletPath("/restricted"); processor.decide(fi, cad);
request.setScheme("http"); assertEquals(response.getRedirectedUrl(),
request.setServerPort(8000); "http://localhost:8000/demo/jcaptcha.do");
processor.setMaxRequestsBeforeFirstTest(1);
MockHttpServletResponse response = new MockHttpServletResponse(); response = decideWithNewResponse(cad, processor, request);
MockFilterChain chain = new MockFilterChain(); assertEquals(response.getRedirectedUrl(), null);
FilterInvocation fi = new FilterInvocation(request, response, chain);
processor.decide(fi, cad); response = decideWithNewResponse(cad, processor, request);
assertEquals("http://localhost:8000/demo/jcaptcha.do", response assertEquals(response.getRedirectedUrl(),
.getRedirectedUrl()); "http://localhost:8000/demo/jcaptcha.do");
processor.setMaxRequestsBeforeFirstTest(1); processor.setMaxRequestsBeforeFirstTest(2);
processor.setMaxMillisBeforeReTest(0);
response = decideWithNewResponse(cad, processor, request); response = decideWithNewResponse(cad, processor, request);
assertEquals(null, response.getRedirectedUrl()); assertEquals(null, response.getRedirectedUrl());
response = decideWithNewResponse(cad, processor, request); response = decideWithNewResponse(cad, processor, request);
assertEquals("http://localhost:8000/demo/jcaptcha.do", response assertEquals("http://localhost:8000/demo/jcaptcha.do", response
.getRedirectedUrl()); .getRedirectedUrl());
}
processor.setMaxRequestsBeforeFirstTest(2); public void testDecideRequestsFirstTestMillis() throws Exception {
processor.setMaxRequestsBeforeReTest(0); ConfigAttributeDefinition cad = new ConfigAttributeDefinition();
cad.addConfigAttribute(new SecurityConfig("SOME_IGNORED_ATTRIBUTE"));
cad.addConfigAttribute(new SecurityConfig(
"REQUIRES_HUMAN_AFTER_MAX_MILLIS"));
response = decideWithNewResponse(cad, processor, request); CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
assertEquals(null, response.getRedirectedUrl()); SecurityContextHolder.setContext(context);
response = decideWithNewResponse(cad, processor, request); CaptchaChannelProcessor processor = new CaptchaChannelProcessor();
assertEquals("http://localhost:8000/demo/jcaptcha.do", response CaptchaEntryPoint epoint = new CaptchaEntryPoint();
.getRedirectedUrl()); epoint.setCaptchaFormUrl("/jcaptcha.do");
epoint.setIncludeOriginalRequest(false);
}
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");
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);
}
}
/*
// 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();
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");
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());
Thread.sleep(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());
Thread.sleep(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); processor.setEntryPoint(epoint);
assertEquals(null, response.getRedirectedUrl());
response = decideWithNewResponse(cad, processor, request); MockHttpServletRequest request = new MockHttpServletRequest();
assertEquals(null, response.getRedirectedUrl()); request.setQueryString("info=true");
request.setServerName("localhost");
request.setContextPath("/demo");
request.setServletPath("/restricted");
request.setScheme("http");
request.setServerPort(8000);
Thread.sleep(100); MockHttpServletResponse response = new MockHttpServletResponse();
MockFilterChain chain = new MockFilterChain();
FilterInvocation fi = new FilterInvocation(request, response, chain);
response = decideWithNewResponse(cad, processor, request); processor.decide(fi, cad);
assertEquals("http://localhost:8000/demo/jcaptcha.do", response assertEquals("http://localhost:8000/demo/jcaptcha.do", response
.getRedirectedUrl()); .getRedirectedUrl());
}
public void testDecideBoth() throws Exception { processor.setMaxRequestsBeforeFirstTest(1);
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(); response = decideWithNewResponse(cad, processor, request);
SecurityContextHolder.setContext(context); assertEquals(null, response.getRedirectedUrl());
CaptchaChannelProcessor processor = new CaptchaChannelProcessor(); response = decideWithNewResponse(cad, processor, request);
CaptchaEntryPoint epoint = new CaptchaEntryPoint(); assertEquals("http://localhost:8000/demo/jcaptcha.do", response
epoint.setCaptchaFormUrl("/jcaptcha.do"); .getRedirectedUrl());
processor.setEntryPoint(epoint);
MockHttpServletRequest request = new MockHttpServletRequest(); processor.setMaxRequestsBeforeFirstTest(2);
request.setQueryString("info=true"); processor.setMaxRequestsBeforeReTest(0);
request.setServerName("localhost");
request.setContextPath("/demo");
request.setServletPath("/restricted");
request.setScheme("http");
request.setServerPort(8000);
MockHttpServletResponse response = new MockHttpServletResponse(); response = decideWithNewResponse(cad, processor, request);
MockFilterChain chain = new MockFilterChain(); assertEquals(null, response.getRedirectedUrl());
FilterInvocation fi = new FilterInvocation(request, response, chain);
processor.decide(fi, cad); response = decideWithNewResponse(cad, processor, request);
assertEquals("http://localhost:8000/demo/jcaptcha.do", response assertEquals("http://localhost:8000/demo/jcaptcha.do", response
.getRedirectedUrl()); .getRedirectedUrl());
processor.setMaxRequestsBeforeFirstTest(1); }
response = decideWithNewResponse(cad, processor, request); public void testDecideRequestsReTest() throws Exception {
assertEquals(response.getRedirectedUrl(), null); ConfigAttributeDefinition cad = new ConfigAttributeDefinition();
cad.addConfigAttribute(new SecurityConfig("SOME_IGNORED_ATTRIBUTE"));
cad.addConfigAttribute(new SecurityConfig(
"REQUIRES_HUMAN_AFTER_MAX_REQUESTS"));
response = decideWithNewResponse(cad, processor, request); CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
assertEquals("http://localhost:8000/demo/jcaptcha.do", response SecurityContextHolder.setContext(context);
.getRedirectedUrl());
processor.setMaxMillisBeforeReTest(100); CaptchaChannelProcessor processor = new CaptchaChannelProcessor();
processor.setMaxRequestsBeforeReTest(2); CaptchaEntryPoint epoint = new CaptchaEntryPoint();
epoint.setCaptchaFormUrl("/jcaptcha.do");
epoint.setIncludeOriginalRequest(false);
processor.setEntryPoint(epoint);
response = decideWithNewResponse(cad, processor, request); MockHttpServletRequest request = new MockHttpServletRequest();
assertEquals("http://localhost:8000/demo/jcaptcha.do", response request.setQueryString("info=true");
.getRedirectedUrl()); request.setServerName("localhost");
request.setContextPath("/demo");
request.setServletPath("/restricted");
request.setScheme("http");
request.setServerPort(8000);
context.setHuman(); MockHttpServletResponse response = new MockHttpServletResponse();
SecurityContextHolder.setContext(context); MockFilterChain chain = new MockFilterChain();
FilterInvocation fi = new FilterInvocation(request, response, chain);
processor.decide(fi, cad);
assertEquals("http://localhost:8000/demo/jcaptcha.do", response
.getRedirectedUrl());
response = decideWithNewResponse(cad, processor, request); processor.setMaxRequestsBeforeFirstTest(1);
assertEquals(null, response.getRedirectedUrl());
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());
Thread.sleep(100); response = decideWithNewResponse(cad, processor, request);
assertEquals(null, response.getRedirectedUrl());
response = decideWithNewResponse(cad, processor, request); response = decideWithNewResponse(cad, processor, request);
assertEquals("http://localhost:8000/demo/jcaptcha.do", response assertEquals("http://localhost:8000/demo/jcaptcha.do", response
.getRedirectedUrl()); .getRedirectedUrl());
response = decideWithNewResponse(cad, processor, request); processor.setMaxMillisBeforeReTest(0);
assertEquals("http://localhost:8000/demo/jcaptcha.do", response context.setHuman();
.getRedirectedUrl()); SecurityContextHolder.setContext(context);
response = decideWithNewResponse(cad, processor, request);
assertEquals(null, response.getRedirectedUrl());
context.setHuman(); response = decideWithNewResponse(cad, processor, request);
SecurityContextHolder.setContext(context); assertEquals(null, response.getRedirectedUrl());
response = decideWithNewResponse(cad, processor, request); response = decideWithNewResponse(cad, processor, request);
assertEquals(null, response.getRedirectedUrl()); assertEquals("http://localhost:8000/demo/jcaptcha.do", response
.getRedirectedUrl());
response = decideWithNewResponse(cad, processor, request); context.setHuman();
assertEquals(null, response.getRedirectedUrl()); SecurityContextHolder.setContext(context);
response = decideWithNewResponse(cad, processor, request); response = decideWithNewResponse(cad, processor, request);
assertEquals("http://localhost:8000/demo/jcaptcha.do", response assertEquals(null, response.getRedirectedUrl());
.getRedirectedUrl());
response = decideWithNewResponse(cad, processor, request); response = decideWithNewResponse(cad, processor, request);
assertEquals("http://localhost:8000/demo/jcaptcha.do", response assertEquals(null, response.getRedirectedUrl());
.getRedirectedUrl());
context.setHuman(); response = decideWithNewResponse(cad, processor, request);
SecurityContextHolder.setContext(context); assertEquals("http://localhost:8000/demo/jcaptcha.do", response
.getRedirectedUrl());
}
response = decideWithNewResponse(cad, processor, request); private MockHttpServletResponse decideWithNewResponse(
assertEquals(null, response.getRedirectedUrl()); 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;
}
Thread.sleep(100); public void testDecideRejectsNulls() throws Exception {
CaptchaChannelProcessor processor = new CaptchaChannelProcessor();
processor.setEntryPoint(new CaptchaEntryPoint());
processor.afterPropertiesSet();
response = decideWithNewResponse(cad, processor, request); try {
assertEquals("http://localhost:8000/demo/jcaptcha.do", response processor.decide(null, null);
.getRedirectedUrl()); fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertTrue(true);
}
}
response = decideWithNewResponse(cad, processor, request); public void testDecideMillis() throws Exception {
assertEquals("http://localhost:8000/demo/jcaptcha.do", response ConfigAttributeDefinition cad = new ConfigAttributeDefinition();
.getRedirectedUrl()); cad.addConfigAttribute(new SecurityConfig("SOME_IGNORED_ATTRIBUTE"));
} cad.addConfigAttribute(new SecurityConfig(
*/ "REQUIRES_HUMAN_AFTER_MAX_MILLIS"));
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 CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
.getRequiresHumanAfterMaxRequestsKeyword()); SecurityContextHolder.setContext(context);
processor.setRequiresHumanAfterMaxRequestsKeyword("Y");
assertEquals("Y", processor.getRequiresHumanAfterMaxRequestsKeyword());
assertEquals(0, processor.getMaxRequestsBeforeFirstTest()); CaptchaChannelProcessor processor = new CaptchaChannelProcessor();
processor.setMaxRequestsBeforeFirstTest(1); CaptchaEntryPoint epoint = new CaptchaEntryPoint();
assertEquals(1, processor.getMaxRequestsBeforeFirstTest()); epoint.setCaptchaFormUrl("/jcaptcha.do");
epoint.setIncludeOriginalRequest(false);
assertEquals(-1, processor.getMaxRequestsBeforeReTest()); processor.setEntryPoint(epoint);
processor.setMaxRequestsBeforeReTest(11);
assertEquals(11, processor.getMaxRequestsBeforeReTest());
assertEquals(-1, processor.getMaxMillisBeforeReTest()); MockHttpServletRequest request = new MockHttpServletRequest();
processor.setMaxMillisBeforeReTest(111); request.setQueryString("info=true");
assertEquals(111, processor.getMaxMillisBeforeReTest()); request.setServerName("localhost");
request.setContextPath("/demo");
request.setServletPath("/restricted");
request.setScheme("http");
request.setServerPort(8000);
assertTrue(processor.getEntryPoint() == null); MockHttpServletResponse response = new MockHttpServletResponse();
processor.setEntryPoint(new CaptchaEntryPoint()); MockFilterChain chain = new MockFilterChain();
assertTrue(processor.getEntryPoint() != null); FilterInvocation fi = new FilterInvocation(request, response, chain);
}
public void testMissingEntryPoint() throws Exception { processor.decide(fi, cad);
CaptchaChannelProcessor processor = new CaptchaChannelProcessor(); assertEquals("http://localhost:8000/demo/jcaptcha.do", response
processor.setEntryPoint(null); .getRedirectedUrl());
try { processor.setMaxRequestsBeforeFirstTest(1);
processor.afterPropertiesSet();
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertEquals("entryPoint required", expected.getMessage());
}
}
public void testMissingKeyword() throws Exception { response = decideWithNewResponse(cad, processor, request);
CaptchaChannelProcessor processor = new CaptchaChannelProcessor(); assertEquals(response.getRedirectedUrl(), null);
processor.setRequiresHumanAfterMaxMillisKeyword(null);
try { response = decideWithNewResponse(cad, processor, request);
processor.afterPropertiesSet(); assertEquals("http://localhost:8000/demo/jcaptcha.do", response
fail("Should have thrown IllegalArgumentException"); .getRedirectedUrl());
} catch (IllegalArgumentException expected) {
} processor.setMaxMillisBeforeReTest(100);
processor.setRequiresHumanAfterMaxMillisKeyword("");
try { response = decideWithNewResponse(cad, processor, request);
processor.afterPropertiesSet(); assertEquals("http://localhost:8000/demo/jcaptcha.do", response
fail("Should have thrown IllegalArgumentException"); .getRedirectedUrl());
} catch (IllegalArgumentException expected) {
} context.setHuman();
processor.setRequiresHumanAfterMaxRequestsKeyword(""); SecurityContextHolder.setContext(context);
try { response = decideWithNewResponse(cad, processor, request);
processor.afterPropertiesSet(); assertEquals(null, response.getRedirectedUrl());
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
} waitFor(100);
processor.setRequiresHumanAfterMaxRequestsKeyword(null); response = decideWithNewResponse(cad, processor, request);
assertEquals("http://localhost:8000/demo/jcaptcha.do", response
try { .getRedirectedUrl());
processor.afterPropertiesSet();
fail("Should have thrown IllegalArgumentException"); processor.setMaxRequestsBeforeReTest(0);
} catch (IllegalArgumentException expected) { context.setHuman();
SecurityContextHolder.setContext(context);
}
response = decideWithNewResponse(cad, processor, request);
} assertEquals(null, response.getRedirectedUrl());
public void testSupports() { response = decideWithNewResponse(cad, processor, request);
CaptchaChannelProcessor processor = new CaptchaChannelProcessor(); assertEquals(null, response.getRedirectedUrl());
assertTrue(processor.supports(new SecurityConfig(processor
.getRequiresHumanAfterMaxMillisKeyword()))); waitFor(100);
assertTrue(processor.supports(new SecurityConfig(processor
.getRequiresHumanAfterMaxRequestsKeyword()))); response = decideWithNewResponse(cad, processor, request);
assertEquals("http://localhost:8000/demo/jcaptcha.do", response
assertTrue(processor.supports(new SecurityConfig( .getRedirectedUrl());
"REQUIRES_HUMAN_AFTER_MAX_REQUESTS")));
assertTrue(processor.supports(new SecurityConfig( context.setHuman();
"REQUIRES_HUMAN_AFTER_MAX_MILLIS"))); SecurityContextHolder.setContext(context);
assertFalse(processor.supports(null)); response = decideWithNewResponse(cad, processor, request);
assertEquals(null, response.getRedirectedUrl());
assertFalse(processor.supports(new SecurityConfig("NOT_SUPPORTED")));
} 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;
}
} }

View File

@ -15,371 +15,416 @@
package net.sf.acegisecurity.captcha; package net.sf.acegisecurity.captcha;
import java.util.HashMap;
import java.util.Map;
import junit.framework.TestCase; import junit.framework.TestCase;
import net.sf.acegisecurity.MockPortResolver; import net.sf.acegisecurity.MockPortResolver;
import net.sf.acegisecurity.securechannel.RetryWithHttpEntryPoint;
import net.sf.acegisecurity.util.PortMapperImpl; import net.sf.acegisecurity.util.PortMapperImpl;
import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse; 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 * @author marc antoine Garrigue
* @version $Id: RetryWithHttpEntryPointTests.java,v 1.4 2005/04/11 01:07:02 * @version $Id$
* luke_t Exp $
*/ */
public class CaptchaEntryPointTests extends TestCase { public class CaptchaEntryPointTests extends TestCase {
// ~ Methods // ~ Methods
// ================================================================ // ================================================================
public final void setUp() throws Exception { public final void setUp() throws Exception {
super.setUp(); super.setUp();
} }
public static void main(String[] args) { public static void main(String[] args) {
junit.textui.TestRunner.run(CaptchaEntryPointTests.class); junit.textui.TestRunner.run(CaptchaEntryPointTests.class);
} }
public void testDetectsMissingCaptchaFormUrl() throws Exception { public void testDetectsMissingCaptchaFormUrl() throws Exception {
CaptchaEntryPoint ep = new CaptchaEntryPoint(); CaptchaEntryPoint ep = new CaptchaEntryPoint();
ep.setPortMapper(new PortMapperImpl()); ep.setPortMapper(new PortMapperImpl());
ep.setPortResolver(new MockPortResolver(80, 443)); ep.setPortResolver(new MockPortResolver(80, 443));
try { try {
ep.afterPropertiesSet(); ep.afterPropertiesSet();
fail("Should have thrown IllegalArgumentException"); fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) { } catch (IllegalArgumentException expected) {
assertEquals("captchaFormUrl must be specified", expected assertEquals("captchaFormUrl must be specified", expected
.getMessage()); .getMessage());
} }
} }
public void testDetectsMissingPortMapper() throws Exception { public void testDetectsMissingPortMapper() throws Exception {
CaptchaEntryPoint ep = new CaptchaEntryPoint(); CaptchaEntryPoint ep = new CaptchaEntryPoint();
ep.setCaptchaFormUrl("xxx"); ep.setCaptchaFormUrl("xxx");
ep.setPortMapper(null); ep.setPortMapper(null);
try { try {
ep.afterPropertiesSet(); ep.afterPropertiesSet();
fail("Should have thrown IllegalArgumentException"); fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) { } catch (IllegalArgumentException expected) {
assertEquals("portMapper must be specified", expected.getMessage()); assertEquals("portMapper must be specified", expected.getMessage());
} }
} }
public void testDetectsMissingPortResolver() throws Exception { public void testDetectsMissingPortResolver() throws Exception {
CaptchaEntryPoint ep = new CaptchaEntryPoint(); CaptchaEntryPoint ep = new CaptchaEntryPoint();
ep.setCaptchaFormUrl("xxx"); ep.setCaptchaFormUrl("xxx");
ep.setPortResolver(null); ep.setPortResolver(null);
try { try {
ep.afterPropertiesSet(); ep.afterPropertiesSet();
fail("Should have thrown IllegalArgumentException"); fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) { } catch (IllegalArgumentException expected) {
assertEquals("portResolver must be specified", expected assertEquals("portResolver must be specified", expected
.getMessage()); .getMessage());
} }
} }
public void testGettersSetters() { public void testGettersSetters() {
CaptchaEntryPoint ep = new CaptchaEntryPoint(); CaptchaEntryPoint ep = new CaptchaEntryPoint();
ep.setCaptchaFormUrl("/hello"); ep.setCaptchaFormUrl("/hello");
ep.setPortMapper(new PortMapperImpl()); ep.setPortMapper(new PortMapperImpl());
ep.setPortResolver(new MockPortResolver(8080, 8443)); ep.setPortResolver(new MockPortResolver(8080, 8443));
assertEquals("/hello", ep.getCaptchaFormUrl()); assertEquals("/hello", ep.getCaptchaFormUrl());
assertTrue(ep.getPortMapper() != null); assertTrue(ep.getPortMapper() != null);
assertTrue(ep.getPortResolver() != null); assertTrue(ep.getPortResolver() != null);
assertEquals("originalRequest", ep.getOriginalRequestParameterName()); assertEquals("original_requestUrl", ep.getOriginalRequestUrlParameterName());
ep.setOriginalRequestParameterName("Z"); ep.setOriginalRequestUrlParameterName("Z");
assertEquals("Z", ep.getOriginalRequestParameterName()); assertEquals("Z", ep.getOriginalRequestUrlParameterName());
assertEquals(false, ep.isIncludeOriginalRequest()); assertEquals(true, ep.isIncludeOriginalRequest());
ep.setIncludeOriginalRequest(true); ep.setIncludeOriginalRequest(false);
assertEquals(true, ep.isIncludeOriginalRequest()); assertEquals(false, ep.isIncludeOriginalRequest());
assertEquals(false, ep.isOutsideWebApp()); assertEquals(false, ep.isOutsideWebApp());
ep.setOutsideWebApp(true); ep.setOutsideWebApp(true);
assertEquals(true, ep.isOutsideWebApp()); assertEquals(true, ep.isOutsideWebApp());
ep.setForceHttps(false); ep.setForceHttps(false);
assertFalse(ep.getForceHttps()); assertFalse(ep.getForceHttps());
ep.setForceHttps(true); ep.setForceHttps(true);
assertTrue(ep.getForceHttps()); assertTrue(ep.getForceHttps());
} }
public void testHttpsOperationFromOriginalHttpUrl() throws Exception { public void testHttpsOperationFromOriginalHttpUrl() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/some_path");
request.setScheme("http");
request.setServerName("www.example.com");
request.setContextPath("/bigWebApp");
request.setServerPort(80);
MockHttpServletResponse response = new MockHttpServletResponse(); request.setRequestURI("/some_path");
request.setScheme("http");
request.setServerName("www.example.com");
request.setContextPath("/bigWebApp");
request.setServerPort(80);
CaptchaEntryPoint ep = new CaptchaEntryPoint(); MockHttpServletResponse response = new MockHttpServletResponse();
ep.setCaptchaFormUrl("/hello");
ep.setPortMapper(new PortMapperImpl());
ep.setForceHttps(true);
ep.setPortMapper(new PortMapperImpl());
ep.setPortResolver(new MockPortResolver(80, 443));
ep.afterPropertiesSet();
ep.commence(request, response); CaptchaEntryPoint ep = new CaptchaEntryPoint();
assertEquals("https://www.example.com/bigWebApp/hello", response ep.setIncludeOriginalRequest(false);
.getRedirectedUrl()); ep.setCaptchaFormUrl("/hello");
ep.setPortMapper(new PortMapperImpl());
ep.setForceHttps(true);
ep.setPortMapper(new PortMapperImpl());
ep.setPortResolver(new MockPortResolver(80, 443));
ep.afterPropertiesSet();
request.setServerPort(8080); ep.commence(request, response);
response = new MockHttpServletResponse(); assertEquals("https://www.example.com/bigWebApp/hello", response
ep.setPortResolver(new MockPortResolver(8080, 8443)); .getRedirectedUrl());
ep.commence(request, response);
assertEquals("https://www.example.com:8443/bigWebApp/hello", response
.getRedirectedUrl());
// Now test an unusual custom HTTP:HTTPS is handled properly request.setServerPort(8080);
request.setServerPort(8888); response = new MockHttpServletResponse();
response = new MockHttpServletResponse(); ep.setPortResolver(new MockPortResolver(8080, 8443));
ep.commence(request, response); ep.commence(request, response);
assertEquals("https://www.example.com:8443/bigWebApp/hello", response assertEquals("https://www.example.com:8443/bigWebApp/hello", response
.getRedirectedUrl()); .getRedirectedUrl());
PortMapperImpl portMapper = new PortMapperImpl(); // Now test an unusual custom HTTP:HTTPS is handled properly
Map map = new HashMap(); request.setServerPort(8888);
map.put("8888", "9999"); response = new MockHttpServletResponse();
portMapper.setPortMappings(map); ep.commence(request, response);
response = new MockHttpServletResponse(); assertEquals("https://www.example.com:8443/bigWebApp/hello", response
.getRedirectedUrl());
ep = new CaptchaEntryPoint(); PortMapperImpl portMapper = new PortMapperImpl();
ep.setCaptchaFormUrl("/hello"); Map map = new HashMap();
ep.setPortMapper(new PortMapperImpl()); map.put("8888", "9999");
ep.setForceHttps(true); portMapper.setPortMappings(map);
ep.setPortMapper(portMapper); response = new MockHttpServletResponse();
ep.setPortResolver(new MockPortResolver(8888, 9999));
ep.afterPropertiesSet();
ep.commence(request, response); ep = new CaptchaEntryPoint();
assertEquals("https://www.example.com:9999/bigWebApp/hello", response ep.setCaptchaFormUrl("/hello");
.getRedirectedUrl()); ep.setPortMapper(new PortMapperImpl());
} ep.setForceHttps(true);
ep.setPortMapper(portMapper);
ep.setPortResolver(new MockPortResolver(8888, 9999));
ep.setIncludeOriginalRequest(false);
public void testHttpsOperationFromOriginalHttpsUrl() throws Exception { ep.afterPropertiesSet();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/some_path");
request.setScheme("https");
request.setServerName("www.example.com");
request.setContextPath("/bigWebApp");
request.setServerPort(443);
MockHttpServletResponse response = new MockHttpServletResponse(); ep.commence(request, response);
assertEquals("https://www.example.com:9999/bigWebApp/hello", response
.getRedirectedUrl());
}
CaptchaEntryPoint ep = new CaptchaEntryPoint(); public void testHttpsOperationFromOriginalHttpsUrl() throws Exception {
ep.setCaptchaFormUrl("/hello"); MockHttpServletRequest request = new MockHttpServletRequest();
ep.setPortMapper(new PortMapperImpl());
ep.setForceHttps(true);
ep.setPortMapper(new PortMapperImpl());
ep.setPortResolver(new MockPortResolver(80, 443));
ep.afterPropertiesSet();
ep.commence(request, response); request.setRequestURI("/some_path");
assertEquals("https://www.example.com/bigWebApp/hello", response request.setScheme("https");
.getRedirectedUrl()); request.setServerName("www.example.com");
request.setContextPath("/bigWebApp");
request.setServerPort(443);
request.setServerPort(8443); MockHttpServletResponse response = new MockHttpServletResponse();
response = new MockHttpServletResponse();
ep.setPortResolver(new MockPortResolver(8080, 8443));
ep.commence(request, response);
assertEquals("https://www.example.com:8443/bigWebApp/hello", response
.getRedirectedUrl());
}
public void testNormalOperation() throws Exception { CaptchaEntryPoint ep = new CaptchaEntryPoint();
CaptchaEntryPoint ep = new CaptchaEntryPoint(); ep.setIncludeOriginalRequest(false);
ep.setCaptchaFormUrl("/hello"); ep.setCaptchaFormUrl("/hello");
ep.setPortMapper(new PortMapperImpl()); ep.setPortMapper(new PortMapperImpl());
ep.setPortResolver(new MockPortResolver(80, 443)); ep.setForceHttps(true);
ep.afterPropertiesSet(); ep.setPortMapper(new PortMapperImpl());
ep.setPortResolver(new MockPortResolver(80, 443));
ep.afterPropertiesSet();
MockHttpServletRequest request = new MockHttpServletRequest(); ep.commence(request, response);
request.setRequestURI("/some_path"); assertEquals("https://www.example.com/bigWebApp/hello", response
request.setContextPath("/bigWebApp"); .getRedirectedUrl());
request.setScheme("http");
request.setServerName("www.example.com");
request.setContextPath("/bigWebApp");
request.setServerPort(80);
MockHttpServletResponse response = new MockHttpServletResponse(); 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());
}
ep.afterPropertiesSet(); public void testNormalOperation() throws Exception {
ep.commence(request, response); CaptchaEntryPoint ep = new CaptchaEntryPoint();
assertEquals("http://www.example.com/bigWebApp/hello", response ep.setCaptchaFormUrl("/hello");
.getRedirectedUrl()); ep.setPortMapper(new PortMapperImpl());
} ep.setPortResolver(new MockPortResolver(80, 443));
ep.afterPropertiesSet();
ep.setIncludeOriginalRequest(false);
public void testOperationWhenHttpsRequestsButHttpsPortUnknown()
throws Exception {
CaptchaEntryPoint ep = new CaptchaEntryPoint();
ep.setCaptchaFormUrl("/hello");
ep.setPortMapper(new PortMapperImpl());
ep.setPortResolver(new MockPortResolver(8888, 1234));
ep.setForceHttps(true);
ep.afterPropertiesSet();
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/some_path"); request.setRequestURI("/some_path");
request.setContextPath("/bigWebApp"); request.setContextPath("/bigWebApp");
request.setScheme("http"); request.setScheme("http");
request.setServerName("www.example.com"); request.setServerName("www.example.com");
request.setContextPath("/bigWebApp"); request.setContextPath("/bigWebApp");
request.setServerPort(8888); // NB: Port we can't resolve request.setServerPort(80);
MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletResponse response = new MockHttpServletResponse();
ep.afterPropertiesSet(); ep.afterPropertiesSet();
ep.commence(request, response); ep.commence(request, response);
assertEquals("http://www.example.com/bigWebApp/hello", response
.getRedirectedUrl());
}
// Response doesn't switch to HTTPS, as we didn't know HTTP port 8888 to public void testOperationWhenHttpsRequestsButHttpsPortUnknown()
// HTTP port mapping throws Exception {
assertEquals("http://www.example.com:8888/bigWebApp/hello", response CaptchaEntryPoint ep = new CaptchaEntryPoint();
.getRedirectedUrl()); ep.setCaptchaFormUrl("/hello");
} ep.setPortMapper(new PortMapperImpl());
ep.setPortResolver(new MockPortResolver(8888, 1234));
ep.setForceHttps(true);
ep.setIncludeOriginalRequest(false);
public void testOperationWithOriginalRequestIncludes() throws Exception { ep.afterPropertiesSet();
CaptchaEntryPoint ep = new CaptchaEntryPoint();
ep.setCaptchaFormUrl("/hello");
PortMapperImpl mapper = new PortMapperImpl();
mapper.getTranslatedPortMappings().put(new Integer(8888),
new Integer(1234));
ep.setPortMapper(mapper);
ep.setPortResolver(new MockPortResolver(8888, 1234)); MockHttpServletRequest request = new MockHttpServletRequest();
ep.setIncludeOriginalRequest(true); request.setRequestURI("/some_path");
ep.afterPropertiesSet(); request.setContextPath("/bigWebApp");
request.setScheme("http");
request.setServerName("www.example.com");
request.setContextPath("/bigWebApp");
request.setServerPort(8888); // NB: Port we can't resolve
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse();
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 ep.afterPropertiesSet();
ep.commence(request, response);
MockHttpServletResponse response = new MockHttpServletResponse(); // 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());
}
ep.afterPropertiesSet(); public void testOperationWithOriginalRequestIncludes() throws Exception {
ep.commence(request, response); CaptchaEntryPoint ep = new CaptchaEntryPoint();
assertEquals( ep.setCaptchaFormUrl("/hello");
"http://www.example.com:8888/hello?originalRequest=http://www.example.com:8888/some_path", PortMapperImpl mapper = new PortMapperImpl();
response.getRedirectedUrl()); mapper.getTranslatedPortMappings().put(new Integer(8888),
new Integer(1234));
ep.setPortMapper(mapper);
// test the query params ep.setPortResolver(new MockPortResolver(8888, 1234));
request.addParameter("name", "value"); ep.setIncludeOriginalRequest(true);
response = new MockHttpServletResponse(); ep.afterPropertiesSet();
ep.commence(request, response);
assertEquals(
"http://www.example.com:8888/hello?originalRequest=http://www.example.com:8888/some_path?name=value",
response.getRedirectedUrl());
// test the multiple query params MockHttpServletRequest request = new MockHttpServletRequest();
request.addParameter("name", "value"); request.setMethod("post");
request.addParameter("name1", "value2"); request.setRequestURI("/some_path");
response = new MockHttpServletResponse(); request.setScheme("http");
ep.commence(request, response); request.setServerName("www.example.com");
assertEquals( // request.setContextPath("/bigWebApp");
"http://www.example.com:8888/hello?originalRequest=http://www.example.com:8888/some_path?name=value&name1=value2", // TODO correct this when the getRequestUrl from mock works...
response.getRedirectedUrl());
// test add parameter to captcha form url?? request.setServerPort(8888); // NB: Port we can't resolve
ep.setCaptchaFormUrl("/hello?toto=titi"); MockHttpServletResponse response = new MockHttpServletResponse();
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",
response.getRedirectedUrl());
// with forcing!!! ep.afterPropertiesSet();
ep.setForceHttps(true); ep.commence(request, response);
response = new MockHttpServletResponse(); assertEquals(
ep.commence(request, response); "http://www.example.com:8888/hello?original_requestUrl="
assertEquals( + URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8")
"https://www.example.com:1234/hello?toto=titi&originalRequest=http://www.example.com:8888/some_path?name=value&name1=value2", + "&original_request_method=post",
response.getRedirectedUrl()); 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());
public void testOperationWithOutsideWebApp() throws Exception { // test the multiple query params
CaptchaEntryPoint ep = new CaptchaEntryPoint(); ep.setIncludeOriginalParameters(true);
ep.setCaptchaFormUrl("https://www.jcaptcha.net/dotest/");
PortMapperImpl mapper = new PortMapperImpl();
mapper.getTranslatedPortMappings().put(new Integer(8888),
new Integer(1234));
ep.setPortMapper(mapper);
ep.setPortResolver(new MockPortResolver(8888, 1234)); request.addParameter("name", "value");
ep.setIncludeOriginalRequest(true); request.addParameter("name1", "value2");
ep.setOutsideWebApp(true); 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());
ep.afterPropertiesSet(); // test add parameter to captcha form url??
MockHttpServletRequest request = new MockHttpServletRequest();
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 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());
MockHttpServletResponse response = new MockHttpServletResponse(); // 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());
ep.afterPropertiesSet(); }
ep.commence(request, response);
assertEquals(
"https://www.jcaptcha.net/dotest/?originalRequest=http://www.example.com:8888/some_path",
response.getRedirectedUrl());
// test the query params public void testOperationWithOutsideWebApp() throws Exception {
request.addParameter("name", "value"); CaptchaEntryPoint ep = new CaptchaEntryPoint();
response = new MockHttpServletResponse(); ep.setCaptchaFormUrl("https://www.jcaptcha.net/dotest/");
ep.commence(request, response); PortMapperImpl mapper = new PortMapperImpl();
assertEquals( mapper.getTranslatedPortMappings().put(new Integer(8888),
"https://www.jcaptcha.net/dotest/?originalRequest=http://www.example.com:8888/some_path?name=value", new Integer(1234));
response.getRedirectedUrl()); ep.setPortMapper(mapper);
// test the multiple query params ep.setPortResolver(new MockPortResolver(8888, 1234));
request.addParameter("name", "value"); ep.setIncludeOriginalRequest(true);
request.addParameter("name1", "value2"); ep.setOutsideWebApp(true);
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",
response.getRedirectedUrl());
// test add parameter to captcha form url?? 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...
ep.setCaptchaFormUrl("https://www.jcaptcha.net/dotest/?toto=titi"); request.setServerPort(8888); // NB: Port we can't resolve
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",
response.getRedirectedUrl());
// with forcing!!! MockHttpServletResponse response = new MockHttpServletResponse();
ep.setForceHttps(true);
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",
response.getRedirectedUrl());
} 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());
// 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());
// 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/?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());
// 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());
}
} }

View File

@ -1,64 +1,85 @@
/* 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; package net.sf.acegisecurity.captcha;
import net.sf.acegisecurity.context.SecurityContextImplTests; import net.sf.acegisecurity.context.SecurityContextImplTests;
/**
* Tests {@link CaptchaSecurityContextImpl}.
*
* @author marc antoine Garrigue
* @version $Id$
*/
public class CaptchaSecurityContextImplTests extends SecurityContextImplTests { public class CaptchaSecurityContextImplTests extends SecurityContextImplTests {
public void testDefaultValues() { public void testDefaultValues() {
CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
assertEquals("should not be human", false, context.isHuman()); assertEquals("should not be human", false, context.isHuman());
assertEquals("should be 0", 0, context assertEquals("should be 0", 0, context
.getLastPassedCaptchaDateInMillis()); .getLastPassedCaptchaDateInMillis());
assertEquals("should be 0", 0, context assertEquals("should be 0", 0, context
.getHumanRestrictedResourcesRequestsCount()); .getHumanRestrictedResourcesRequestsCount());
} }
public void testSetHuman() { public void testSetHuman() {
CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
context.setHuman(); context.setHuman();
assertEquals("should be human", true, context.isHuman()); assertEquals("should be human", true, context.isHuman());
assertTrue("should be more than 0", context assertTrue("should be more than 0", context
.getLastPassedCaptchaDateInMillis() .getLastPassedCaptchaDateInMillis()
- now >= 0); - now >= 0);
assertTrue("should be less than 0,1 seconde", context assertTrue("should be less than 0,1 seconde", context
.getLastPassedCaptchaDateInMillis() .getLastPassedCaptchaDateInMillis()
- now < 100); - now < 100);
assertEquals("should be 0", 0, context assertEquals("should be 0", 0, context
.getHumanRestrictedResourcesRequestsCount()); .getHumanRestrictedResourcesRequestsCount());
} }
public void testIncrementRequests() { public void testIncrementRequests() {
CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
context.setHuman(); context.setHuman();
assertEquals("should be human", true, context.isHuman()); assertEquals("should be human", true, context.isHuman());
assertEquals("should be 0", 0, context assertEquals("should be 0", 0, context
.getHumanRestrictedResourcesRequestsCount()); .getHumanRestrictedResourcesRequestsCount());
context.incrementHumanRestrictedRessoucesRequestsCount(); context.incrementHumanRestrictedRessoucesRequestsCount();
assertEquals("should be 1", 1, context assertEquals("should be 1", 1, context
.getHumanRestrictedResourcesRequestsCount()); .getHumanRestrictedResourcesRequestsCount());
} }
public void testResetHuman() { public void testResetHuman() {
CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
context.setHuman(); context.setHuman();
assertEquals("should be human", true, context.isHuman()); assertEquals("should be human", true, context.isHuman());
assertEquals("should be 0", 0, context assertEquals("should be 0", 0, context
.getHumanRestrictedResourcesRequestsCount()); .getHumanRestrictedResourcesRequestsCount());
context.incrementHumanRestrictedRessoucesRequestsCount(); context.incrementHumanRestrictedRessoucesRequestsCount();
assertEquals("should be 1", 1, context assertEquals("should be 1", 1, context
.getHumanRestrictedResourcesRequestsCount()); .getHumanRestrictedResourcesRequestsCount());
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
context.setHuman(); context.setHuman();
assertEquals("should be 0", 0, context assertEquals("should be 0", 0, context
.getHumanRestrictedResourcesRequestsCount()); .getHumanRestrictedResourcesRequestsCount());
assertTrue("should be more than 0", context assertTrue("should be more than 0", context
.getLastPassedCaptchaDateInMillis() .getLastPassedCaptchaDateInMillis()
- now >= 0); - now >= 0);
assertTrue("should be less than 0,1 seconde", context assertTrue("should be less than 0,1 seconde", context
.getLastPassedCaptchaDateInMillis() .getLastPassedCaptchaDateInMillis()
- now < 100); - now < 100);
} }
} }

View File

@ -1,83 +1,115 @@
/* 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; package net.sf.acegisecurity.captcha;
import junit.framework.TestCase; import junit.framework.TestCase;
import net.sf.acegisecurity.context.SecurityContextHolder; import net.sf.acegisecurity.context.SecurityContextHolder;
import net.sf.acegisecurity.util.MockFilterChain; import net.sf.acegisecurity.util.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletRequest;
/**
* Tests {@link CaptchaValidationProcessingFilter}.
*
* @author marc antoine Garrigue
* @version $Id$
*/
public class CaptchaValidationProcessingFilterTests extends TestCase { public class CaptchaValidationProcessingFilterTests extends TestCase {
/* /*
*/ */
public void testAfterPropertiesSet() throws Exception { public void testAfterPropertiesSet() throws Exception {
CaptchaValidationProcessingFilter filter = new CaptchaValidationProcessingFilter(); CaptchaValidationProcessingFilter filter = new CaptchaValidationProcessingFilter();
try { try {
filter.afterPropertiesSet(); filter.afterPropertiesSet();
fail("should have thrown an invalid argument exception"); fail("should have thrown an invalid argument exception");
} catch (Exception e) { } catch (Exception e) {
assertTrue("should be an InvalidArgumentException", assertTrue("should be an InvalidArgumentException",
IllegalArgumentException.class.isAssignableFrom(e IllegalArgumentException.class.isAssignableFrom(e
.getClass())); .getClass()));
} }
filter.setCaptchaService(new MockCaptchaServiceProxy());
filter.afterPropertiesSet();
} 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()));
}
/*
* 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 * Test method for
* 'net.sf.acegisecurity.captcha.CaptchaValidationProcessingFilter.doFilter(ServletRequest, * 'net.sf.acegisecurity.captcha.CaptchaValidationProcessingFilter.doFilter(ServletRequest,
* ServletResponse, FilterChain)' * ServletResponse, FilterChain)'
*/ */
public void testDoFilterWithRequestParameter() throws Exception { public void testDoFilterWithoutRequestParameter() throws Exception {
CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
SecurityContextHolder.setContext(context); 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());
MockHttpServletRequest request = new MockHttpServletRequest(); }
request
.addParameter(
CaptchaValidationProcessingFilter.CAPTCHA_VALIDATION_SECURITY_PARAMETER_KEY,
"");
CaptchaValidationProcessingFilter filter = new CaptchaValidationProcessingFilter(); /*
MockCaptchaServiceProxy service = new MockCaptchaServiceProxy(); * Test method for
MockFilterChain chain = new MockFilterChain(true); * 'net.sf.acegisecurity.captcha.CaptchaValidationProcessingFilter.doFilter(ServletRequest,
filter.setCaptchaService(service); * ServletResponse, FilterChain)'
filter.doFilter(request, null, chain); */
assertTrue("should have been called", service.hasBeenCalled); public void testDoFilterWithRequestParameter() throws Exception {
assertFalse("context should not have been updated", context.isHuman()); CaptchaSecurityContext context = new CaptchaSecurityContextImpl();
// test with valid SecurityContextHolder.setContext(context);
service.valid = true;
filter.doFilter(request, null, chain);
assertTrue("should have been called", service.hasBeenCalled);
assertTrue("context should have been updated", context.isHuman());
} MockHttpServletRequest request = new MockHttpServletRequest();
CaptchaValidationProcessingFilter filter = new CaptchaValidationProcessingFilter();
request
.addParameter(
filter.getCaptchaValidationParameter(),
"");
MockCaptchaServiceProxy service = new MockCaptchaServiceProxy();
MockFilterChain chain = new MockFilterChain(true);
filter.setCaptchaService(service);
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());
}
} }

View File

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