25 changed files with 0 additions and 2588 deletions
@ -1,36 +0,0 @@ |
|||||||
<?xml version="1.0"?> |
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> |
|
||||||
<parent> |
|
||||||
<artifactId>spring-security-parent</artifactId> |
|
||||||
<groupId>org.springframework.security</groupId> |
|
||||||
<version>3.0.0.CI-SNAPSHOT</version> |
|
||||||
</parent> |
|
||||||
<modelVersion>4.0.0</modelVersion> |
|
||||||
<groupId>org.springframework.security</groupId> |
|
||||||
<artifactId>spring-security-captcha</artifactId> |
|
||||||
<name>Spring Security - Captcha module</name> |
|
||||||
|
|
||||||
<dependencies> |
|
||||||
<dependency> |
|
||||||
<groupId>org.springframework.security</groupId> |
|
||||||
<artifactId>spring-security-core</artifactId> |
|
||||||
<version>${project.version}</version> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>org.springframework.security</groupId> |
|
||||||
<artifactId>spring-security-core</artifactId> |
|
||||||
<version>${project.version}</version> |
|
||||||
<classifier>tests</classifier> |
|
||||||
<scope>test</scope> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>javax.servlet</groupId> |
|
||||||
<artifactId>servlet-api</artifactId> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>org.springframework</groupId> |
|
||||||
<artifactId>org.springframework.test</artifactId> |
|
||||||
<scope>test</scope> |
|
||||||
</dependency> |
|
||||||
</dependencies> |
|
||||||
</project> |
|
||||||
@ -1,60 +0,0 @@ |
|||||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
/* |
|
||||||
* Copyright (c) 2005 Your Corporation. All Rights Reserved. |
|
||||||
*/ |
|
||||||
package org.springframework.security.captcha; |
|
||||||
|
|
||||||
/** |
|
||||||
* Return false if the number of requests for captcha protcted URLs for the user |
|
||||||
* exceeds the threshold value. |
|
||||||
* |
|
||||||
* <br/> |
|
||||||
* Default keyword : <tt>REQUIRES_CAPTCHA_ABOVE_THRESHOLD_REQUESTS</tt> |
|
||||||
* |
|
||||||
* @author Marc-Antoine Garrigue |
|
||||||
* @version $Id$ |
|
||||||
*/ |
|
||||||
public class AlwaysTestAfterMaxRequestsCaptchaChannelProcessor extends CaptchaChannelProcessorTemplate { |
|
||||||
//~ Static fields/initializers =====================================================================================
|
|
||||||
|
|
||||||
/** Keyword for this channelProcessor */ |
|
||||||
public static final String DEFAULT_KEYWORD = "REQUIRES_CAPTCHA_ABOVE_THRESHOLD_REQUESTS"; |
|
||||||
|
|
||||||
//~ Constructors ===================================================================================================
|
|
||||||
|
|
||||||
public AlwaysTestAfterMaxRequestsCaptchaChannelProcessor() { |
|
||||||
this.setKeyword(DEFAULT_KEYWORD); |
|
||||||
} |
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
|
||||||
|
|
||||||
/** |
|
||||||
* |
|
||||||
* @return false if the number of requests for captcha protected URLs exceeds the threshold. |
|
||||||
*/ |
|
||||||
boolean isContextValidConcerningHumanity(CaptchaSecurityContext context) { |
|
||||||
if (context.getHumanRestrictedResourcesRequestsCount() < getThreshold()) { |
|
||||||
logger.debug("context is valid : request count < thresold"); |
|
||||||
|
|
||||||
return true; |
|
||||||
} else { |
|
||||||
logger.debug("context is not valid : request count > thresold"); |
|
||||||
|
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,58 +0,0 @@ |
|||||||
/* Copyright 2004, 2005, 2006 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 org.springframework.security.captcha; |
|
||||||
|
|
||||||
/** |
|
||||||
* Return false if the time in millis since the last captcha test is less than the threshold;<br/> |
|
||||||
* Default keyword : <tt>REQUIRES_CAPTCHA_AFTER_THRESHOLD_IN_MILLIS</tt>. |
|
||||||
* |
|
||||||
* @author Marc-Antoine Garrigue |
|
||||||
* @version $Id$ |
|
||||||
*/ |
|
||||||
public class AlwaysTestAfterTimeInMillisCaptchaChannelProcessor extends CaptchaChannelProcessorTemplate { |
|
||||||
//~ Static fields/initializers =====================================================================================
|
|
||||||
|
|
||||||
/** Keyword for this channelProcessor */ |
|
||||||
public static final String DEFAULT_KEYWORD = "REQUIRES_CAPTCHA_AFTER_THRESHOLD_IN_MILLIS"; |
|
||||||
|
|
||||||
//~ Constructors ===================================================================================================
|
|
||||||
|
|
||||||
public AlwaysTestAfterTimeInMillisCaptchaChannelProcessor() { |
|
||||||
|
|
||||||
this.setKeyword(DEFAULT_KEYWORD); |
|
||||||
} |
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
|
||||||
|
|
||||||
/** |
|
||||||
* Returns false if the time (in milliseconds) since the last captcha validation is greater than the |
|
||||||
* threshold value. |
|
||||||
* |
|
||||||
* @param context the CaptchaSecurityContext |
|
||||||
* |
|
||||||
*/ |
|
||||||
boolean isContextValidConcerningHumanity(CaptchaSecurityContext context) { |
|
||||||
if ((System.currentTimeMillis() - context.getLastPassedCaptchaDateInMillis()) < getThreshold()) { |
|
||||||
logger.debug("context is valid : current time - last passed captcha date < threshold"); |
|
||||||
|
|
||||||
return true; |
|
||||||
} else { |
|
||||||
logger.debug("context is not valid : current time - last passed captcha date > threshold"); |
|
||||||
|
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,79 +0,0 @@ |
|||||||
/* Copyright 2004, 2005, 2006 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 org.springframework.security.captcha; |
|
||||||
|
|
||||||
import org.springframework.util.Assert; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Return false if the average time in millis between any CaptchaChannelProcessorTemplate mapped |
|
||||||
* urls requests is greater than the threshold value or the context is not human;<br /> |
|
||||||
* Default keyword : <tt>REQUIRES_CAPTCHA_BELOW_AVERAGE_TIME_IN_MILLIS_REQUESTS</tt> <br> |
|
||||||
* Note : before first humanity check |
|
||||||
* |
|
||||||
* @author Marc-Antoine Garrigue |
|
||||||
* @version $Id$ |
|
||||||
*/ |
|
||||||
public class AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor extends CaptchaChannelProcessorTemplate { |
|
||||||
//~ Static fields/initializers =====================================================================================
|
|
||||||
|
|
||||||
/** Keyword for this channelProcessor */ |
|
||||||
public static final String DEFAULT_KEYWORD = "REQUIRES_CAPTCHA_BELOW_AVERAGE_TIME_IN_MILLIS_REQUESTS"; |
|
||||||
|
|
||||||
//~ Constructors ===================================================================================================
|
|
||||||
|
|
||||||
public AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor() { |
|
||||||
this.setKeyword(DEFAULT_KEYWORD); |
|
||||||
} |
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
|
||||||
|
|
||||||
/** |
|
||||||
* Verify that threshold is > 0 |
|
||||||
* |
|
||||||
* @throws Exception if false |
|
||||||
*/ |
|
||||||
public void afterPropertiesSet() throws Exception { |
|
||||||
super.afterPropertiesSet(); |
|
||||||
Assert.isTrue(getThreshold() > 0, "thresold must be > 0"); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* |
|
||||||
*/ |
|
||||||
boolean isContextValidConcerningHumanity(CaptchaSecurityContext context) { |
|
||||||
int req = context.getHumanRestrictedResourcesRequestsCount(); |
|
||||||
float thresold = getThreshold(); |
|
||||||
float duration = System.currentTimeMillis() - context.getLastPassedCaptchaDateInMillis(); |
|
||||||
float average; |
|
||||||
|
|
||||||
if (req == 0) { |
|
||||||
average = thresold + 1; |
|
||||||
} else { |
|
||||||
average = duration / req; |
|
||||||
} |
|
||||||
|
|
||||||
if (context.isHuman() && (average > thresold)) { |
|
||||||
logger.debug("context is valid : average time between requests < threshold && is human"); |
|
||||||
|
|
||||||
return true; |
|
||||||
} else { |
|
||||||
logger.debug("context is not valid : average time between requests > threshold or is not human"); |
|
||||||
|
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,150 +0,0 @@ |
|||||||
/* Copyright 2004, 2005, 2006 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 org.springframework.security.captcha; |
|
||||||
|
|
||||||
import org.springframework.security.ConfigAttribute; |
|
||||||
|
|
||||||
import org.springframework.security.context.SecurityContextHolder; |
|
||||||
|
|
||||||
import org.springframework.security.intercept.web.FilterInvocation; |
|
||||||
|
|
||||||
import org.springframework.security.securechannel.ChannelEntryPoint; |
|
||||||
import org.springframework.security.securechannel.ChannelProcessor; |
|
||||||
|
|
||||||
import org.apache.commons.logging.Log; |
|
||||||
import org.apache.commons.logging.LogFactory; |
|
||||||
|
|
||||||
import org.springframework.beans.factory.InitializingBean; |
|
||||||
|
|
||||||
import org.springframework.util.Assert; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
|
|
||||||
import java.util.Iterator; |
|
||||||
|
|
||||||
import javax.servlet.ServletException; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* CaptchaChannel template : Ensures the user has enough human privileges by review of the {@link |
|
||||||
* CaptchaSecurityContext} and using an abstract routine {@link |
|
||||||
* #isContextValidConcerningHumanity(CaptchaSecurityContext)} (implemented by sub classes) |
|
||||||
* <p>The component uses 2 main parameters for its configuration : |
|
||||||
* <ul> |
|
||||||
* <li>a keyword to be mapped to urls in the {@link |
|
||||||
* org.springframework.security.securechannel.ChannelProcessingFilter} configuration<br> |
|
||||||
* default value provided by sub classes.</li> |
|
||||||
* <li>and a threshold : used by the routine {@link |
|
||||||
* #isContextValidConcerningHumanity(CaptchaSecurityContext)} to evaluate whether the {@link |
|
||||||
* CaptchaSecurityContext} is valid default value = 0</li> |
|
||||||
* </ul> |
|
||||||
* </p> |
|
||||||
* |
|
||||||
* @author Marc-Antoine Garrigue |
|
||||||
* @version $Id$ |
|
||||||
*/ |
|
||||||
public abstract class CaptchaChannelProcessorTemplate implements ChannelProcessor, InitializingBean { |
|
||||||
//~ Instance fields ================================================================================================
|
|
||||||
|
|
||||||
private ChannelEntryPoint entryPoint; |
|
||||||
protected Log logger = LogFactory.getLog(this.getClass()); |
|
||||||
private String keyword = null; |
|
||||||
private int thresold = 0; |
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
|
||||||
|
|
||||||
/** |
|
||||||
* Verify if entryPoint and keyword are ok |
|
||||||
* |
|
||||||
* @throws Exception if not |
|
||||||
*/ |
|
||||||
public void afterPropertiesSet() throws Exception { |
|
||||||
Assert.notNull(entryPoint, "entryPoint required"); |
|
||||||
Assert.hasLength(keyword, "keyword required"); |
|
||||||
} |
|
||||||
|
|
||||||
public void decide(FilterInvocation invocation, java.util.List<ConfigAttribute> config) throws IOException, ServletException { |
|
||||||
if ((invocation == null) || (config == null)) { |
|
||||||
throw new IllegalArgumentException("Nulls cannot be provided"); |
|
||||||
} |
|
||||||
|
|
||||||
CaptchaSecurityContext context = null; |
|
||||||
context = (CaptchaSecurityContext) SecurityContextHolder.getContext(); |
|
||||||
|
|
||||||
Iterator iter = config.iterator(); |
|
||||||
|
|
||||||
while (iter.hasNext()) { |
|
||||||
ConfigAttribute attribute = (ConfigAttribute) iter.next(); |
|
||||||
|
|
||||||
if (supports(attribute)) { |
|
||||||
logger.debug("supports this attribute : " + attribute); |
|
||||||
|
|
||||||
if (!isContextValidConcerningHumanity(context)) { |
|
||||||
logger.debug("context is not allowed to access ressource, redirect to captcha entry point"); |
|
||||||
redirectToEntryPoint(invocation); |
|
||||||
} else { |
|
||||||
logger.debug("has been successfully checked this keyword, increment request count"); |
|
||||||
context.incrementHumanRestrictedResourcesRequestsCount(); |
|
||||||
} |
|
||||||
} else { |
|
||||||
logger.debug("do not support this attribute"); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public ChannelEntryPoint getEntryPoint() { |
|
||||||
return entryPoint; |
|
||||||
} |
|
||||||
|
|
||||||
public String getKeyword() { |
|
||||||
return keyword; |
|
||||||
} |
|
||||||
|
|
||||||
public int getThreshold() { |
|
||||||
return thresold; |
|
||||||
} |
|
||||||
|
|
||||||
abstract boolean isContextValidConcerningHumanity(CaptchaSecurityContext context); |
|
||||||
|
|
||||||
private void redirectToEntryPoint(FilterInvocation invocation) |
|
||||||
throws IOException, ServletException { |
|
||||||
if (logger.isDebugEnabled()) { |
|
||||||
logger.debug("context is not valid : redirecting to entry point"); |
|
||||||
} |
|
||||||
|
|
||||||
entryPoint.commence(invocation.getRequest(), invocation.getResponse()); |
|
||||||
} |
|
||||||
|
|
||||||
public void setEntryPoint(ChannelEntryPoint entryPoint) { |
|
||||||
this.entryPoint = entryPoint; |
|
||||||
} |
|
||||||
|
|
||||||
public void setKeyword(String keyword) { |
|
||||||
this.keyword = keyword; |
|
||||||
} |
|
||||||
|
|
||||||
public void setThreshold(int thresold) { |
|
||||||
this.thresold = thresold; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean supports(ConfigAttribute attribute) { |
|
||||||
if ((attribute != null) && (keyword.equals(attribute.getAttribute()))) { |
|
||||||
return true; |
|
||||||
} else { |
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,393 +0,0 @@ |
|||||||
/* Copyright 2004, 2005, 2006 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 org.springframework.security.captcha; |
|
||||||
|
|
||||||
import org.springframework.security.securechannel.ChannelEntryPoint; |
|
||||||
|
|
||||||
import org.springframework.security.util.PortMapper; |
|
||||||
import org.springframework.security.util.PortMapperImpl; |
|
||||||
import org.springframework.security.util.PortResolver; |
|
||||||
import org.springframework.security.util.PortResolverImpl; |
|
||||||
|
|
||||||
import org.apache.commons.logging.Log; |
|
||||||
import org.apache.commons.logging.LogFactory; |
|
||||||
|
|
||||||
import org.springframework.beans.factory.InitializingBean; |
|
||||||
|
|
||||||
import org.springframework.util.Assert; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
import java.io.UnsupportedEncodingException; |
|
||||||
|
|
||||||
import java.net.URLEncoder; |
|
||||||
|
|
||||||
import java.util.Enumeration; |
|
||||||
|
|
||||||
import javax.servlet.ServletException; |
|
||||||
import javax.servlet.ServletRequest; |
|
||||||
import javax.servlet.ServletResponse; |
|
||||||
import javax.servlet.http.HttpServletRequest; |
|
||||||
import javax.servlet.http.HttpServletResponse; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* The captcha entry point : redirect to the captcha test page. |
|
||||||
* <p> |
|
||||||
* This entry point can force the use of SSL : see {@link #getForceHttps()} |
|
||||||
* <p> |
|
||||||
* This entry point allows internal OR external redirect : see {@link #setOutsideWebApp(boolean)}<br /> |
|
||||||
* / Original request can be added to the redirect path using a custom translation : see |
|
||||||
* {@link #setIncludeOriginalRequest(boolean)}<br /> |
|
||||||
* The original request is translated using URLEncoding and the following translation mapping in the redirect url : |
|
||||||
* <ul> |
|
||||||
* <li>original url => {@link #getOriginalRequestUrlParameterName()}</li> |
|
||||||
* <li>If {@link #isIncludeOriginalParameters()}</li> |
|
||||||
* <li>original method => {@link #getOriginalRequestMethodParameterName()}</li> |
|
||||||
* <li>original parameters => {@link #getOriginalRequestParametersParameterName()}</li> |
|
||||||
* <li>The original parameters string is contructed using : |
|
||||||
* <ul> |
|
||||||
* <li>a parameter separator {@link #getOriginalRequestParametersSeparator()}</li> |
|
||||||
* <li>a parameter name value pair separator for each parameter {@link |
|
||||||
* #getOriginalRequestParametersNameValueSeparator()}</li> |
|
||||||
* </ul> |
|
||||||
* </li> |
|
||||||
* </ul> |
|
||||||
* <br><br> |
|
||||||
* Default values : |
|
||||||
* <pre> |
|
||||||
* forceHttps = false |
|
||||||
* includesOriginalRequest = true |
|
||||||
* includesOriginalParameters = false |
|
||||||
* isOutsideWebApp = false |
|
||||||
* originalRequestUrlParameterName = original_requestUrl |
|
||||||
* originalRequestParametersParameterName = original_request_parameters |
|
||||||
* originalRequestParametersNameValueSeparator = __ |
|
||||||
* originalRequestParametersSeparator = ;; |
|
||||||
* originalRequestMethodParameterName = original_request_method |
|
||||||
* urlEncodingCharset = UTF-8 |
|
||||||
* </pre> |
|
||||||
* </p> |
|
||||||
* |
|
||||||
* @author Marc-Antoine Garrigue |
|
||||||
* @version $Id$ |
|
||||||
*/ |
|
||||||
public class CaptchaEntryPoint implements ChannelEntryPoint, InitializingBean { |
|
||||||
//~ Static fields/initializers =====================================================================================
|
|
||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(CaptchaEntryPoint.class); |
|
||||||
|
|
||||||
//~ Instance fields ================================================================================================
|
|
||||||
|
|
||||||
private PortMapper portMapper = new PortMapperImpl(); |
|
||||||
private PortResolver portResolver = new PortResolverImpl(); |
|
||||||
private String captchaFormUrl; |
|
||||||
private String originalRequestMethodParameterName = "original_request_method"; |
|
||||||
private String originalRequestParametersNameValueSeparator = "__"; |
|
||||||
private String originalRequestParametersParameterName = "original_request_parameters"; |
|
||||||
private String originalRequestParametersSeparator = ";;"; |
|
||||||
private String originalRequestUrlParameterName = "original_requestUrl"; |
|
||||||
private String urlEncodingCharset = "UTF-8"; |
|
||||||
private boolean forceHttps = false; |
|
||||||
private boolean includeOriginalParameters = false; |
|
||||||
private boolean includeOriginalRequest = true; |
|
||||||
private boolean isOutsideWebApp = false; |
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
|
||||||
|
|
||||||
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); |
|
||||||
} |
|
||||||
|
|
||||||
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); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void commence(HttpServletRequest request, HttpServletResponse 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()); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* |
|
||||||
* @return the captcha test page to redirect to. |
|
||||||
*/ |
|
||||||
public String getCaptchaFormUrl() { |
|
||||||
return captchaFormUrl; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean getForceHttps() { |
|
||||||
return forceHttps; |
|
||||||
} |
|
||||||
|
|
||||||
public String getOriginalRequestMethodParameterName() { |
|
||||||
return originalRequestMethodParameterName; |
|
||||||
} |
|
||||||
|
|
||||||
public String getOriginalRequestParametersNameValueSeparator() { |
|
||||||
return originalRequestParametersNameValueSeparator; |
|
||||||
} |
|
||||||
|
|
||||||
public String getOriginalRequestParametersParameterName() { |
|
||||||
return originalRequestParametersParameterName; |
|
||||||
} |
|
||||||
|
|
||||||
public String getOriginalRequestParametersSeparator() { |
|
||||||
return originalRequestParametersSeparator; |
|
||||||
} |
|
||||||
|
|
||||||
public String getOriginalRequestUrlParameterName() { |
|
||||||
return originalRequestUrlParameterName; |
|
||||||
} |
|
||||||
|
|
||||||
public PortMapper getPortMapper() { |
|
||||||
return portMapper; |
|
||||||
} |
|
||||||
|
|
||||||
public PortResolver getPortResolver() { |
|
||||||
return portResolver; |
|
||||||
} |
|
||||||
|
|
||||||
public String getUrlEncodingCharset() { |
|
||||||
return urlEncodingCharset; |
|
||||||
} |
|
||||||
|
|
||||||
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); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public boolean isIncludeOriginalParameters() { |
|
||||||
return includeOriginalParameters; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean isIncludeOriginalRequest() { |
|
||||||
return includeOriginalRequest; |
|
||||||
} |
|
||||||
|
|
||||||
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> |
|
||||||
* |
|
||||||
* @param captchaFormUrl |
|
||||||
*/ |
|
||||||
public void setCaptchaFormUrl(String captchaFormUrl) { |
|
||||||
this.captchaFormUrl = captchaFormUrl; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Set to true to force captcha form access to be via https. If this value is true (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 void setIncludeOriginalParameters(boolean includeOriginalParameters) { |
|
||||||
this.includeOriginalParameters = includeOriginalParameters; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* If set to true, the original request url will be appended to the redirect url using the {@link |
|
||||||
* #getOriginalRequestUrlParameterName()}. |
|
||||||
* |
|
||||||
* @param includeOriginalRequest |
|
||||||
*/ |
|
||||||
public void setIncludeOriginalRequest(boolean includeOriginalRequest) { |
|
||||||
this.includeOriginalRequest = includeOriginalRequest; |
|
||||||
} |
|
||||||
|
|
||||||
public void setOriginalRequestMethodParameterName(String originalRequestMethodParameterName) { |
|
||||||
this.originalRequestMethodParameterName = originalRequestMethodParameterName; |
|
||||||
} |
|
||||||
|
|
||||||
public void setOriginalRequestParametersNameValueSeparator(String originalRequestParametersNameValueSeparator) { |
|
||||||
this.originalRequestParametersNameValueSeparator = originalRequestParametersNameValueSeparator; |
|
||||||
} |
|
||||||
|
|
||||||
public void setOriginalRequestParametersParameterName(String originalRequestParametersParameterName) { |
|
||||||
this.originalRequestParametersParameterName = originalRequestParametersParameterName; |
|
||||||
} |
|
||||||
|
|
||||||
public void setOriginalRequestParametersSeparator(String originalRequestParametersSeparator) { |
|
||||||
this.originalRequestParametersSeparator = originalRequestParametersSeparator; |
|
||||||
} |
|
||||||
|
|
||||||
public void setOriginalRequestUrlParameterName(String originalRequestUrlParameterName) { |
|
||||||
this.originalRequestUrlParameterName = originalRequestUrlParameterName; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* if set to true, the {@link #commence(ServletRequest, ServletResponse)} method uses the {@link |
|
||||||
* #getCaptchaFormUrl()} as a complete URL, else it as a 'inside WebApp' path. |
|
||||||
* |
|
||||||
* @param isOutsideWebApp |
|
||||||
*/ |
|
||||||
public void setOutsideWebApp(boolean isOutsideWebApp) { |
|
||||||
this.isOutsideWebApp = isOutsideWebApp; |
|
||||||
} |
|
||||||
|
|
||||||
public void setPortMapper(PortMapper portMapper) { |
|
||||||
this.portMapper = portMapper; |
|
||||||
} |
|
||||||
|
|
||||||
public void setPortResolver(PortResolver portResolver) { |
|
||||||
this.portResolver = portResolver; |
|
||||||
} |
|
||||||
|
|
||||||
public void setUrlEncodingCharset(String urlEncodingCharset) { |
|
||||||
this.urlEncodingCharset = urlEncodingCharset; |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,57 +0,0 @@ |
|||||||
/* Copyright 2004, 2005, 2006 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 org.springframework.security.captcha; |
|
||||||
|
|
||||||
import org.springframework.security.context.SecurityContext; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Interface that adds humanity concerns to the SecurityContext |
|
||||||
* |
|
||||||
* @author Marc-Antoine Garrigue |
|
||||||
* @version $Id$ |
|
||||||
*/ |
|
||||||
public interface CaptchaSecurityContext extends SecurityContext { |
|
||||||
//~ Methods ========================================================================================================
|
|
||||||
|
|
||||||
/** |
|
||||||
* |
|
||||||
* @return the number of human restricted resources requested since the last passed captcha. |
|
||||||
*/ |
|
||||||
int getHumanRestrictedResourcesRequestsCount(); |
|
||||||
|
|
||||||
/** |
|
||||||
* |
|
||||||
* @return the date of the last passed Captcha in millis, 0 if the user never passed captcha. |
|
||||||
*/ |
|
||||||
long getLastPassedCaptchaDateInMillis(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Increments the human Restricted Resources Requests Count. |
|
||||||
*/ |
|
||||||
void incrementHumanRestrictedResourcesRequestsCount(); |
|
||||||
|
|
||||||
/** |
|
||||||
* |
|
||||||
* @return true if the current user has already passed a captcha. |
|
||||||
*/ |
|
||||||
boolean isHuman(); |
|
||||||
|
|
||||||
/** |
|
||||||
* set human attribute, should be called after captcha validation. |
|
||||||
*/ |
|
||||||
void setHuman(); |
|
||||||
} |
|
||||||
@ -1,105 +0,0 @@ |
|||||||
/* Copyright 2004, 2005, 2006 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 org.springframework.security.captcha; |
|
||||||
|
|
||||||
import org.springframework.security.context.SecurityContextImpl; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Default CaptchaSecurityContext implementation |
|
||||||
* |
|
||||||
* @author Marc-Antoine Garrigue |
|
||||||
* @version $Id$ |
|
||||||
*/ |
|
||||||
public class CaptchaSecurityContextImpl extends SecurityContextImpl implements CaptchaSecurityContext { |
|
||||||
//~ Instance fields ================================================================================================
|
|
||||||
|
|
||||||
private boolean human; |
|
||||||
private int humanRestrictedResourcesRequestsCount; |
|
||||||
private long lastPassedCaptchaDate; |
|
||||||
|
|
||||||
//~ Constructors ===================================================================================================
|
|
||||||
|
|
||||||
public CaptchaSecurityContextImpl() { |
|
||||||
human = false; |
|
||||||
lastPassedCaptchaDate = 0; |
|
||||||
humanRestrictedResourcesRequestsCount = 0; |
|
||||||
} |
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
|
||||||
|
|
||||||
public boolean equals(Object obj) { |
|
||||||
if (obj instanceof CaptchaSecurityContextImpl) { |
|
||||||
CaptchaSecurityContextImpl rhs = (CaptchaSecurityContextImpl) obj; |
|
||||||
|
|
||||||
if (this.isHuman() != rhs.isHuman()) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
if (this.getHumanRestrictedResourcesRequestsCount() != rhs.getHumanRestrictedResourcesRequestsCount()) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
if (this.getLastPassedCaptchaDateInMillis() != rhs.getLastPassedCaptchaDateInMillis()) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
return super.equals(obj); |
|
||||||
} |
|
||||||
|
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
public int getHumanRestrictedResourcesRequestsCount() { |
|
||||||
return humanRestrictedResourcesRequestsCount; |
|
||||||
} |
|
||||||
|
|
||||||
public long getLastPassedCaptchaDateInMillis() { |
|
||||||
return lastPassedCaptchaDate; |
|
||||||
} |
|
||||||
|
|
||||||
public int hashCode() { |
|
||||||
int code = super.hashCode(); |
|
||||||
code ^= this.humanRestrictedResourcesRequestsCount; |
|
||||||
code ^= this.lastPassedCaptchaDate; |
|
||||||
|
|
||||||
if (this.isHuman()) { |
|
||||||
code ^= -37; |
|
||||||
} |
|
||||||
|
|
||||||
return code; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Method to increment the human Restricted Resources Requests Count; |
|
||||||
*/ |
|
||||||
public void incrementHumanRestrictedResourcesRequestsCount() { |
|
||||||
humanRestrictedResourcesRequestsCount++; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean isHuman() { |
|
||||||
return human; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Reset the lastPassedCaptchaDate and count. |
|
||||||
*/ |
|
||||||
public void setHuman() { |
|
||||||
this.human = true; |
|
||||||
this.lastPassedCaptchaDate = System.currentTimeMillis(); |
|
||||||
this.humanRestrictedResourcesRequestsCount = 0; |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,35 +0,0 @@ |
|||||||
/* Copyright 2004, 2005, 2006 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 org.springframework.security.captcha; |
|
||||||
|
|
||||||
/** |
|
||||||
* Provide a common interface for captcha validation. |
|
||||||
* |
|
||||||
* @author Marc-Antoine Garrigue |
|
||||||
* @version $Id$ |
|
||||||
*/ |
|
||||||
public interface CaptchaServiceProxy { |
|
||||||
//~ Methods ========================================================================================================
|
|
||||||
|
|
||||||
/** |
|
||||||
* |
|
||||||
* @param id the id token |
|
||||||
* @param captchaResponse the user response |
|
||||||
* |
|
||||||
* @return true if the response is validated by the back end captcha service. |
|
||||||
*/ |
|
||||||
boolean validateReponseForId(String id, Object captchaResponse); |
|
||||||
} |
|
||||||
@ -1,140 +0,0 @@ |
|||||||
/* Copyright 2004, 2005, 2006 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 org.springframework.security.captcha; |
|
||||||
|
|
||||||
import org.springframework.security.context.SecurityContextHolder; |
|
||||||
|
|
||||||
import org.apache.commons.logging.Log; |
|
||||||
import org.apache.commons.logging.LogFactory; |
|
||||||
|
|
||||||
import org.springframework.beans.factory.InitializingBean; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
|
|
||||||
import javax.servlet.*; |
|
||||||
import javax.servlet.http.HttpServletRequest; |
|
||||||
import javax.servlet.http.HttpSession; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Filter for web integration of the {@link CaptchaServiceProxy}. |
|
||||||
* <p> |
|
||||||
* It basically intercept calls containing the specific validation parameter, uses the {@link CaptchaServiceProxy} to |
|
||||||
* validate the request, and update the {@link CaptchaSecurityContext} if the request passed the validation. |
|
||||||
* <p> |
|
||||||
* This Filter should be placed after the ContextIntegration filter and before the {@link |
|
||||||
* CaptchaChannelProcessorTemplate} filter in the filter stack in order to update the {@link CaptchaSecurityContext} |
|
||||||
* before the humanity verification routine occurs. |
|
||||||
* <p> |
|
||||||
* This filter should only be used in conjunction with the {@link CaptchaSecurityContext}<br> |
|
||||||
* |
|
||||||
* @author marc antoine Garrigue |
|
||||||
* @version $Id$ |
|
||||||
*/ |
|
||||||
public class CaptchaValidationProcessingFilter implements InitializingBean, Filter { |
|
||||||
//~ Static fields/initializers =====================================================================================
|
|
||||||
|
|
||||||
protected static final Log logger = LogFactory.getLog(CaptchaValidationProcessingFilter.class); |
|
||||||
|
|
||||||
//~ Instance fields ================================================================================================
|
|
||||||
|
|
||||||
private CaptchaServiceProxy captchaService; |
|
||||||
private String captchaValidationParameter = "_captcha_parameter"; |
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
|
||||||
|
|
||||||
public void afterPropertiesSet() throws Exception { |
|
||||||
if (this.captchaService == null) { |
|
||||||
throw new IllegalArgumentException("CaptchaServiceProxy must be defined "); |
|
||||||
} |
|
||||||
|
|
||||||
if ((this.captchaValidationParameter == null) || "".equals(captchaValidationParameter)) { |
|
||||||
throw new IllegalArgumentException("captchaValidationParameter must not be empty or null"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Does nothing. We use IoC container lifecycle services instead. |
|
||||||
*/ |
|
||||||
public void destroy() {} |
|
||||||
|
|
||||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) |
|
||||||
throws IOException, ServletException { |
|
||||||
String captchaResponse = request.getParameter(captchaValidationParameter); |
|
||||||
|
|
||||||
if ((request != null) && request instanceof HttpServletRequest && (captchaResponse != null)) { |
|
||||||
logger.debug("captcha validation parameter found"); |
|
||||||
|
|
||||||
// validate the request against CaptchaServiceProxy
|
|
||||||
boolean valid = false; |
|
||||||
|
|
||||||
logger.debug("try to validate"); |
|
||||||
|
|
||||||
//get session
|
|
||||||
HttpSession session = ((HttpServletRequest) request).getSession(); |
|
||||||
|
|
||||||
if (session != null) { |
|
||||||
String id = session.getId(); |
|
||||||
valid = this.captchaService.validateReponseForId(id, captchaResponse); |
|
||||||
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"); |
|
||||||
} |
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) { |
|
||||||
logger.debug("chain ..."); |
|
||||||
} |
|
||||||
|
|
||||||
chain.doFilter(request, response); |
|
||||||
} |
|
||||||
|
|
||||||
public CaptchaServiceProxy getCaptchaService() { |
|
||||||
return captchaService; |
|
||||||
} |
|
||||||
|
|
||||||
public String getCaptchaValidationParameter() { |
|
||||||
return captchaValidationParameter; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Does nothing. We use IoC container lifecycle services instead. |
|
||||||
* |
|
||||||
* @param filterConfig ignored |
|
||||||
* |
|
||||||
* @throws ServletException ignored |
|
||||||
*/ |
|
||||||
public void init(FilterConfig filterConfig) throws ServletException {} |
|
||||||
|
|
||||||
public void setCaptchaService(CaptchaServiceProxy captchaService) { |
|
||||||
this.captchaService = captchaService; |
|
||||||
} |
|
||||||
|
|
||||||
public void setCaptchaValidationParameter(String captchaValidationParameter) { |
|
||||||
this.captchaValidationParameter = captchaValidationParameter; |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,50 +0,0 @@ |
|||||||
/* Copyright 2004, 2005, 2006 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 org.springframework.security.captcha; |
|
||||||
|
|
||||||
/** |
|
||||||
* Return false if any CaptchaChannelProcessorTemplate mapped urls have been requested more than threshold and |
|
||||||
* humanity is false; <br> |
|
||||||
* Default keyword : REQUIRES_CAPTCHA_ONCE_ABOVE_THRESHOLD_REQUESTS</p> |
|
||||||
* |
|
||||||
* @author Marc-Antoine Garrigue |
|
||||||
* @version $Id$ |
|
||||||
*/ |
|
||||||
public class TestOnceAfterMaxRequestsCaptchaChannelProcessor extends CaptchaChannelProcessorTemplate { |
|
||||||
//~ Static fields/initializers =====================================================================================
|
|
||||||
|
|
||||||
public static final String DEFAULT_KEYWORD = "REQUIRES_CAPTCHA_ONCE_ABOVE_THRESHOLD_REQUESTS"; |
|
||||||
|
|
||||||
//~ Constructors ===================================================================================================
|
|
||||||
|
|
||||||
public TestOnceAfterMaxRequestsCaptchaChannelProcessor() { |
|
||||||
this.setKeyword(DEFAULT_KEYWORD); |
|
||||||
} |
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
|
||||||
|
|
||||||
boolean isContextValidConcerningHumanity(CaptchaSecurityContext context) { |
|
||||||
if (context.isHuman() || (context.getHumanRestrictedResourcesRequestsCount() < getThreshold())) { |
|
||||||
logger.debug("context is valid concerning humanity or request count < threshold"); |
|
||||||
|
|
||||||
return true; |
|
||||||
} else { |
|
||||||
logger.debug("context is not valid concerning humanity and request count > threshold"); |
|
||||||
|
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,12 +0,0 @@ |
|||||||
<html> |
|
||||||
<body> |
|
||||||
Captcha classes. Contains :<br/> |
|
||||||
<ul> |
|
||||||
<li>a CaptchaSecurityContext that overrides the default SecurityContext and holds some captcha related informations</li> |
|
||||||
<li>an abstract CaptchaChannelProcessorTemplate and its implementations that test this context according to the configuration</li> |
|
||||||
<li>a CaptchaServiceProxy and a CaptchaValidationProcessingFilter that alows to validate a captcha response and to update the CaptchaSecurity</li> |
|
||||||
<li>a CaptchaEntryPoint that redirects to a captcha page if the CaptchaChannelProcessor implementation decide so</li> |
|
||||||
</ul> |
|
||||||
</body> |
|
||||||
</html> |
|
||||||
|
|
||||||
@ -1,63 +0,0 @@ |
|||||||
/* Copyright 2004, 2005, 2006 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 org.springframework.security.captcha; |
|
||||||
|
|
||||||
import junit.framework.TestCase; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @author Marc-Antoine Garrigue |
|
||||||
*/ |
|
||||||
public class AlwaysTestAfterMaxRequestsCaptchaChannelProcessorTests extends TestCase { |
|
||||||
//~ Instance fields ================================================================================================
|
|
||||||
|
|
||||||
AlwaysTestAfterMaxRequestsCaptchaChannelProcessor alwaysTestAfterMaxRequestsCaptchaChannelProcessor; |
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
|
||||||
|
|
||||||
protected void setUp() throws Exception { |
|
||||||
super.setUp(); |
|
||||||
alwaysTestAfterMaxRequestsCaptchaChannelProcessor = new AlwaysTestAfterMaxRequestsCaptchaChannelProcessor(); |
|
||||||
} |
|
||||||
|
|
||||||
public void testIsContextValidConcerningHumanity() |
|
||||||
throws Exception { |
|
||||||
alwaysTestAfterMaxRequestsCaptchaChannelProcessor.setThreshold(1); |
|
||||||
|
|
||||||
CaptchaSecurityContextImpl context = new CaptchaSecurityContextImpl(); |
|
||||||
assertTrue(alwaysTestAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); |
|
||||||
|
|
||||||
context.incrementHumanRestrictedResourcesRequestsCount(); |
|
||||||
|
|
||||||
alwaysTestAfterMaxRequestsCaptchaChannelProcessor.setThreshold(-1); |
|
||||||
assertFalse(alwaysTestAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); |
|
||||||
|
|
||||||
alwaysTestAfterMaxRequestsCaptchaChannelProcessor.setThreshold(3); |
|
||||||
assertTrue(alwaysTestAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); |
|
||||||
context.incrementHumanRestrictedResourcesRequestsCount(); |
|
||||||
assertTrue(alwaysTestAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); |
|
||||||
context.incrementHumanRestrictedResourcesRequestsCount(); |
|
||||||
assertFalse(alwaysTestAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); |
|
||||||
} |
|
||||||
|
|
||||||
public void testNewContext() { |
|
||||||
CaptchaSecurityContextImpl context = new CaptchaSecurityContextImpl(); |
|
||||||
|
|
||||||
assertFalse(alwaysTestAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); |
|
||||||
alwaysTestAfterMaxRequestsCaptchaChannelProcessor.setThreshold(1); |
|
||||||
assertTrue(alwaysTestAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,84 +0,0 @@ |
|||||||
/* Copyright 2004, 2005, 2006 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 org.springframework.security.captcha; |
|
||||||
|
|
||||||
import junit.framework.*; |
|
||||||
|
|
||||||
import org.springframework.security.captcha.AlwaysTestAfterTimeInMillisCaptchaChannelProcessor; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* WARNING! This test class make some assumptions concerning the compute speed! For example the two following |
|
||||||
* instructions should be computed in the same millis or the test is not valid.<pre><code>context.setHuman(); |
|
||||||
* assertFalse(alwaysTestAfterTimeInMillisCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); |
|
||||||
* </code></pre>This should be the case for most environements unless |
|
||||||
* <ul> |
|
||||||
* <li>you run it on a good old TRS-80</li> |
|
||||||
* <li>you start M$office during this test ;)</li> |
|
||||||
* </ul> |
|
||||||
*/ |
|
||||||
public class AlwaysTestAfterTimeInMillisCaptchaChannelProcessorTests extends TestCase { |
|
||||||
//~ Instance fields ================================================================================================
|
|
||||||
|
|
||||||
AlwaysTestAfterTimeInMillisCaptchaChannelProcessor alwaysTestAfterTimeInMillisCaptchaChannelProcessor; |
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
|
||||||
|
|
||||||
protected void setUp() throws Exception { |
|
||||||
super.setUp(); |
|
||||||
alwaysTestAfterTimeInMillisCaptchaChannelProcessor = new AlwaysTestAfterTimeInMillisCaptchaChannelProcessor(); |
|
||||||
} |
|
||||||
|
|
||||||
public void testEqualsThresold() { |
|
||||||
CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); |
|
||||||
assertFalse(alwaysTestAfterTimeInMillisCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); |
|
||||||
|
|
||||||
//the two following instructions should be computed or the test is not valid (never fails). This should be the case
|
|
||||||
// for most environements unless if you run it on a good old TRS-80 (thanks mom).
|
|
||||||
context.setHuman(); |
|
||||||
assertFalse(alwaysTestAfterTimeInMillisCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); |
|
||||||
} |
|
||||||
/* Commented out as it makes assumptions about the speed of the build server and fails intermittently on |
|
||||||
build.springframework.org - L.T. |
|
||||||
|
|
||||||
public void testIsContextValidConcerningHumanity() |
|
||||||
throws Exception { |
|
||||||
CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); |
|
||||||
alwaysTestAfterTimeInMillisCaptchaChannelProcessor.setThreshold(100); |
|
||||||
context.setHuman(); |
|
||||||
|
|
||||||
while ((System.currentTimeMillis() - context.getLastPassedCaptchaDateInMillis()) < alwaysTestAfterTimeInMillisCaptchaChannelProcessor |
|
||||||
.getThreshold()) { |
|
||||||
assertTrue(alwaysTestAfterTimeInMillisCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); |
|
||||||
context.incrementHumanRestrictedRessoucesRequestsCount(); |
|
||||||
|
|
||||||
long now = System.currentTimeMillis(); |
|
||||||
|
|
||||||
while ((System.currentTimeMillis() - now) < 1) {} |
|
||||||
|
|
||||||
; |
|
||||||
} |
|
||||||
|
|
||||||
assertFalse(alwaysTestAfterTimeInMillisCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); |
|
||||||
} |
|
||||||
*/ |
|
||||||
public void testNewContext() { |
|
||||||
CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); |
|
||||||
|
|
||||||
//alwaysTestAfterTimeInMillisCaptchaChannelProcessor.setThreshold(10);
|
|
||||||
assertFalse(alwaysTestAfterTimeInMillisCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,117 +0,0 @@ |
|||||||
/* Copyright 2004, 2005, 2006 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 org.springframework.security.captcha; |
|
||||||
|
|
||||||
import junit.framework.TestCase; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* DOCUMENT ME! |
|
||||||
* |
|
||||||
* @author $author$ |
|
||||||
* @version $Revision: 2142 $ |
|
||||||
*/ |
|
||||||
public class AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessorTests extends TestCase { |
|
||||||
//~ Instance fields ================================================================================================
|
|
||||||
|
|
||||||
AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor; |
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
|
||||||
|
|
||||||
protected void setUp() throws Exception { |
|
||||||
super.setUp(); |
|
||||||
alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor = new AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor(); |
|
||||||
} |
|
||||||
|
|
||||||
public void testEqualsThresold() { |
|
||||||
CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); |
|
||||||
alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor.setThreshold(100); |
|
||||||
|
|
||||||
context.setHuman(); |
|
||||||
|
|
||||||
long now = System.currentTimeMillis(); |
|
||||||
/* |
|
||||||
while ((System.currentTimeMillis() - now) <= 100) { |
|
||||||
assertTrue(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor |
|
||||||
.isContextValidConcerningHumanity(context)); |
|
||||||
} |
|
||||||
|
|
||||||
context.incrementHumanRestrictedRessoucesRequestsCount(); |
|
||||||
assertTrue(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor.isContextValidConcerningHumanity( |
|
||||||
context)); |
|
||||||
|
|
||||||
context.setHuman(); |
|
||||||
context.incrementHumanRestrictedRessoucesRequestsCount(); |
|
||||||
assertFalse(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor.isContextValidConcerningHumanity( |
|
||||||
context)); |
|
||||||
|
|
||||||
alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor.setThreshold(0); |
|
||||||
context.setHuman(); |
|
||||||
context.incrementHumanRestrictedRessoucesRequestsCount(); |
|
||||||
assertFalse(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor.isContextValidConcerningHumanity( |
|
||||||
context)); |
|
||||||
alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor.setThreshold(0); |
|
||||||
*/ |
|
||||||
} |
|
||||||
/* |
|
||||||
public void testIsContextValidConcerningHumanity() |
|
||||||
throws Exception { |
|
||||||
CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); |
|
||||||
alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor.setThreshold(10); |
|
||||||
context.setHuman(); |
|
||||||
|
|
||||||
while ((System.currentTimeMillis() - context.getLastPassedCaptchaDateInMillis()) < (10 * alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor |
|
||||||
.getThreshold())) { |
|
||||||
assertTrue(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor |
|
||||||
.isContextValidConcerningHumanity(context)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void testNewContext() { |
|
||||||
CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); |
|
||||||
assertFalse(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor.isContextValidConcerningHumanity( |
|
||||||
context)); |
|
||||||
|
|
||||||
context.setHuman(); |
|
||||||
assertTrue(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor.isContextValidConcerningHumanity( |
|
||||||
context)); |
|
||||||
} |
|
||||||
|
|
||||||
public void testShouldPassAbove() { |
|
||||||
CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); |
|
||||||
|
|
||||||
context.setHuman(); |
|
||||||
|
|
||||||
int i = 0; |
|
||||||
|
|
||||||
while ((System.currentTimeMillis() - context.getLastPassedCaptchaDateInMillis()) < (100 * alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor |
|
||||||
.getThreshold())) { |
|
||||||
System.out.println((System.currentTimeMillis() - context.getLastPassedCaptchaDateInMillis())); |
|
||||||
|
|
||||||
context.incrementHumanRestrictedRessoucesRequestsCount(); |
|
||||||
i++; |
|
||||||
|
|
||||||
while ((System.currentTimeMillis() - context.getLastPassedCaptchaDateInMillis()) < (alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor |
|
||||||
.getThreshold() * i)) {} |
|
||||||
|
|
||||||
System.out.println((System.currentTimeMillis() - context.getLastPassedCaptchaDateInMillis())); |
|
||||||
|
|
||||||
assertTrue(alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor |
|
||||||
.isContextValidConcerningHumanity(context)); |
|
||||||
} |
|
||||||
} |
|
||||||
*/ |
|
||||||
} |
|
||||||
@ -1,229 +0,0 @@ |
|||||||
/* Copyright 2004, 2005, 2006 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 org.springframework.security.captcha; |
|
||||||
|
|
||||||
import junit.framework.TestCase; |
|
||||||
|
|
||||||
import org.springframework.security.ConfigAttribute; |
|
||||||
import org.springframework.security.SecurityConfig; |
|
||||||
|
|
||||||
import org.springframework.security.context.SecurityContextHolder; |
|
||||||
|
|
||||||
import org.springframework.security.intercept.web.FilterInvocation; |
|
||||||
|
|
||||||
import org.springframework.mock.web.MockHttpServletRequest; |
|
||||||
import org.springframework.mock.web.MockHttpServletResponse; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
import javax.servlet.ServletException; |
|
||||||
import javax.servlet.FilterChain; |
|
||||||
import javax.servlet.ServletRequest; |
|
||||||
import javax.servlet.ServletResponse; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Tests {@link org.springframework.security.captcha.CaptchaChannelProcessorTemplate} |
|
||||||
* |
|
||||||
* @author marc antoine Garrigue |
|
||||||
* @version $Id$ |
|
||||||
*/ |
|
||||||
public class CaptchaChannelProcessorTemplateTests extends TestCase { |
|
||||||
//~ Methods ========================================================================================================
|
|
||||||
|
|
||||||
private MockHttpServletResponse decideWithNewResponse(List<ConfigAttribute> cad, |
|
||||||
CaptchaChannelProcessorTemplate processor, MockHttpServletRequest request) |
|
||||||
throws IOException, ServletException { |
|
||||||
MockHttpServletResponse response; |
|
||||||
MockFilterChain chain; |
|
||||||
FilterInvocation fi; |
|
||||||
response = new MockHttpServletResponse(); |
|
||||||
chain = new MockFilterChain(); |
|
||||||
fi = new FilterInvocation(request, response, chain); |
|
||||||
processor.decide(fi, cad); |
|
||||||
|
|
||||||
return response; |
|
||||||
} |
|
||||||
|
|
||||||
public void setUp() { |
|
||||||
SecurityContextHolder.clearContext(); |
|
||||||
} |
|
||||||
|
|
||||||
public void tearDown() { |
|
||||||
SecurityContextHolder.clearContext(); |
|
||||||
} |
|
||||||
|
|
||||||
public void testContextRedirect() throws Exception { |
|
||||||
CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor(); |
|
||||||
processor.setKeyword("X"); |
|
||||||
|
|
||||||
List<ConfigAttribute> cad = SecurityConfig.createList("Y"); |
|
||||||
|
|
||||||
CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); |
|
||||||
SecurityContextHolder.setContext(context); |
|
||||||
|
|
||||||
CaptchaEntryPoint epoint = new CaptchaEntryPoint(); |
|
||||||
epoint.setCaptchaFormUrl("/jcaptcha.do"); |
|
||||||
epoint.setIncludeOriginalRequest(false); |
|
||||||
|
|
||||||
processor.setEntryPoint(epoint); |
|
||||||
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.setQueryString("info=true"); |
|
||||||
request.setServerName("localhost"); |
|
||||||
request.setContextPath("/demo"); |
|
||||||
request.setServletPath("/restricted"); |
|
||||||
request.setScheme("http"); |
|
||||||
request.setServerPort(8000); |
|
||||||
|
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse(); |
|
||||||
MockFilterChain chain = new MockFilterChain(); |
|
||||||
FilterInvocation fi = new FilterInvocation(request, response, chain); |
|
||||||
|
|
||||||
processor.decide(fi, cad); |
|
||||||
assertEquals(null, response.getRedirectedUrl()); |
|
||||||
processor.setKeyword("Y"); |
|
||||||
response = decideWithNewResponse(cad, processor, request); |
|
||||||
assertEquals("http://localhost:8000/demo/jcaptcha.do", response.getRedirectedUrl()); |
|
||||||
context.setHuman(); |
|
||||||
response = decideWithNewResponse(cad, processor, request); |
|
||||||
assertEquals(null, response.getRedirectedUrl()); |
|
||||||
} |
|
||||||
|
|
||||||
public void testDecideRejectsNulls() throws Exception { |
|
||||||
CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor(); |
|
||||||
processor.setEntryPoint(new CaptchaEntryPoint()); |
|
||||||
processor.setKeyword("X"); |
|
||||||
processor.afterPropertiesSet(); |
|
||||||
|
|
||||||
try { |
|
||||||
processor.decide(null, null); |
|
||||||
fail("Should have thrown IllegalArgumentException"); |
|
||||||
} catch (IllegalArgumentException expected) { |
|
||||||
assertTrue(true); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void testGettersSetters() { |
|
||||||
CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor(); |
|
||||||
assertEquals(null, processor.getKeyword()); |
|
||||||
processor.setKeyword("X"); |
|
||||||
assertEquals("X", processor.getKeyword()); |
|
||||||
|
|
||||||
assertEquals(0, processor.getThreshold()); |
|
||||||
processor.setThreshold(1); |
|
||||||
assertEquals(1, processor.getThreshold()); |
|
||||||
|
|
||||||
assertTrue(processor.getEntryPoint() == null); |
|
||||||
processor.setEntryPoint(new CaptchaEntryPoint()); |
|
||||||
assertTrue(processor.getEntryPoint() != null); |
|
||||||
} |
|
||||||
|
|
||||||
public void testIncrementRequestCount() throws Exception { |
|
||||||
CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor(); |
|
||||||
processor.setKeyword("X"); |
|
||||||
|
|
||||||
List<ConfigAttribute> cad = SecurityConfig.createList("X"); |
|
||||||
CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); |
|
||||||
SecurityContextHolder.setContext(context); |
|
||||||
|
|
||||||
CaptchaEntryPoint epoint = new CaptchaEntryPoint(); |
|
||||||
epoint.setCaptchaFormUrl("/jcaptcha.do"); |
|
||||||
processor.setEntryPoint(epoint); |
|
||||||
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.setQueryString("info=true"); |
|
||||||
request.setServerName("localhost"); |
|
||||||
request.setContextPath("/demo"); |
|
||||||
request.setServletPath("/restricted"); |
|
||||||
request.setScheme("http"); |
|
||||||
request.setServerPort(8000); |
|
||||||
|
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse(); |
|
||||||
MockFilterChain chain = new MockFilterChain(); |
|
||||||
FilterInvocation fi = new FilterInvocation(request, response, chain); |
|
||||||
|
|
||||||
processor.decide(fi, cad); |
|
||||||
assertEquals(0, context.getHumanRestrictedResourcesRequestsCount()); |
|
||||||
context.setHuman(); |
|
||||||
decideWithNewResponse(cad, processor, request); |
|
||||||
assertEquals(1, context.getHumanRestrictedResourcesRequestsCount()); |
|
||||||
decideWithNewResponse(cad, processor, request); |
|
||||||
assertEquals(2, context.getHumanRestrictedResourcesRequestsCount()); |
|
||||||
processor.setKeyword("Y"); |
|
||||||
decideWithNewResponse(cad, processor, request); |
|
||||||
assertEquals(2, context.getHumanRestrictedResourcesRequestsCount()); |
|
||||||
context = new CaptchaSecurityContextImpl(); |
|
||||||
decideWithNewResponse(cad, processor, request); |
|
||||||
assertEquals(0, context.getHumanRestrictedResourcesRequestsCount()); |
|
||||||
} |
|
||||||
|
|
||||||
public void testMissingEntryPoint() throws Exception { |
|
||||||
CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor(); |
|
||||||
processor.setEntryPoint(null); |
|
||||||
|
|
||||||
try { |
|
||||||
processor.afterPropertiesSet(); |
|
||||||
fail("Should have thrown IllegalArgumentException"); |
|
||||||
} catch (IllegalArgumentException expected) { |
|
||||||
assertEquals("entryPoint required", expected.getMessage()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void testMissingKeyword() throws Exception { |
|
||||||
CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor(); |
|
||||||
processor.setKeyword(null); |
|
||||||
|
|
||||||
try { |
|
||||||
processor.afterPropertiesSet(); |
|
||||||
fail("Should have thrown IllegalArgumentException"); |
|
||||||
} catch (IllegalArgumentException expected) {} |
|
||||||
|
|
||||||
processor.setKeyword(""); |
|
||||||
|
|
||||||
try { |
|
||||||
processor.afterPropertiesSet(); |
|
||||||
fail("Should have thrown IllegalArgumentException"); |
|
||||||
} catch (IllegalArgumentException expected) {} |
|
||||||
} |
|
||||||
|
|
||||||
public void testSupports() { |
|
||||||
CaptchaChannelProcessorTemplate processor = new TestHumanityCaptchaChannelProcessor(); |
|
||||||
processor.setKeyword("X"); |
|
||||||
assertTrue(processor.supports(new SecurityConfig(processor.getKeyword()))); |
|
||||||
|
|
||||||
assertTrue(processor.supports(new SecurityConfig("X"))); |
|
||||||
|
|
||||||
assertFalse(processor.supports(null)); |
|
||||||
|
|
||||||
assertFalse(processor.supports(new SecurityConfig("NOT_SUPPORTED"))); |
|
||||||
} |
|
||||||
|
|
||||||
//~ Inner Classes ==================================================================================================
|
|
||||||
|
|
||||||
private class TestHumanityCaptchaChannelProcessor extends CaptchaChannelProcessorTemplate { |
|
||||||
boolean isContextValidConcerningHumanity(CaptchaSecurityContext context) { |
|
||||||
return context.isHuman(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private static class MockFilterChain implements FilterChain { |
|
||||||
public void doFilter(ServletRequest arg0, ServletResponse arg1) throws IOException, ServletException { |
|
||||||
throw new UnsupportedOperationException("mock method not implemented"); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,386 +0,0 @@ |
|||||||
/* Copyright 2004, 2005, 2006 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 org.springframework.security.captcha; |
|
||||||
|
|
||||||
import junit.framework.TestCase; |
|
||||||
|
|
||||||
import org.springframework.security.MockPortResolver; |
|
||||||
|
|
||||||
import org.springframework.security.util.PortMapperImpl; |
|
||||||
|
|
||||||
import org.springframework.mock.web.MockHttpServletRequest; |
|
||||||
import org.springframework.mock.web.MockHttpServletResponse; |
|
||||||
|
|
||||||
import java.net.URLEncoder; |
|
||||||
|
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Tests {@link CaptchaEntryPoint}. |
|
||||||
* |
|
||||||
* @author marc antoine Garrigue |
|
||||||
* @version $Id$ |
|
||||||
*/ |
|
||||||
public class CaptchaEntryPointTests extends TestCase { |
|
||||||
//~ Methods ========================================================================================================
|
|
||||||
|
|
||||||
public void testDetectsMissingCaptchaFormUrl() throws Exception { |
|
||||||
CaptchaEntryPoint ep = new CaptchaEntryPoint(); |
|
||||||
ep.setPortMapper(new PortMapperImpl()); |
|
||||||
ep.setPortResolver(new MockPortResolver(80, 443)); |
|
||||||
|
|
||||||
try { |
|
||||||
ep.afterPropertiesSet(); |
|
||||||
fail("Should have thrown IllegalArgumentException"); |
|
||||||
} catch (IllegalArgumentException expected) { |
|
||||||
assertEquals("captchaFormUrl must be specified", expected.getMessage()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void testDetectsMissingPortMapper() throws Exception { |
|
||||||
CaptchaEntryPoint ep = new CaptchaEntryPoint(); |
|
||||||
ep.setCaptchaFormUrl("xxx"); |
|
||||||
ep.setPortMapper(null); |
|
||||||
|
|
||||||
try { |
|
||||||
ep.afterPropertiesSet(); |
|
||||||
fail("Should have thrown IllegalArgumentException"); |
|
||||||
} catch (IllegalArgumentException expected) { |
|
||||||
assertEquals("portMapper must be specified", expected.getMessage()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void testDetectsMissingPortResolver() throws Exception { |
|
||||||
CaptchaEntryPoint ep = new CaptchaEntryPoint(); |
|
||||||
ep.setCaptchaFormUrl("xxx"); |
|
||||||
ep.setPortResolver(null); |
|
||||||
|
|
||||||
try { |
|
||||||
ep.afterPropertiesSet(); |
|
||||||
fail("Should have thrown IllegalArgumentException"); |
|
||||||
} catch (IllegalArgumentException expected) { |
|
||||||
assertEquals("portResolver must be specified", expected.getMessage()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void testGettersSetters() { |
|
||||||
CaptchaEntryPoint ep = new CaptchaEntryPoint(); |
|
||||||
ep.setCaptchaFormUrl("/hello"); |
|
||||||
ep.setPortMapper(new PortMapperImpl()); |
|
||||||
ep.setPortResolver(new MockPortResolver(8080, 8443)); |
|
||||||
assertEquals("/hello", ep.getCaptchaFormUrl()); |
|
||||||
assertTrue(ep.getPortMapper() != null); |
|
||||||
assertTrue(ep.getPortResolver() != null); |
|
||||||
|
|
||||||
assertEquals("original_requestUrl", ep.getOriginalRequestUrlParameterName()); |
|
||||||
ep.setOriginalRequestUrlParameterName("Z"); |
|
||||||
assertEquals("Z", ep.getOriginalRequestUrlParameterName()); |
|
||||||
|
|
||||||
assertEquals(true, ep.isIncludeOriginalRequest()); |
|
||||||
ep.setIncludeOriginalRequest(false); |
|
||||||
assertEquals(false, ep.isIncludeOriginalRequest()); |
|
||||||
|
|
||||||
assertEquals(false, ep.isOutsideWebApp()); |
|
||||||
ep.setOutsideWebApp(true); |
|
||||||
assertEquals(true, ep.isOutsideWebApp()); |
|
||||||
|
|
||||||
ep.setForceHttps(false); |
|
||||||
assertFalse(ep.getForceHttps()); |
|
||||||
ep.setForceHttps(true); |
|
||||||
assertTrue(ep.getForceHttps()); |
|
||||||
} |
|
||||||
|
|
||||||
public void testHttpsOperationFromOriginalHttpUrl() |
|
||||||
throws Exception { |
|
||||||
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(); |
|
||||||
|
|
||||||
CaptchaEntryPoint ep = new CaptchaEntryPoint(); |
|
||||||
ep.setIncludeOriginalRequest(false); |
|
||||||
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); |
|
||||||
assertEquals("https://www.example.com/bigWebApp/hello", response.getRedirectedUrl()); |
|
||||||
|
|
||||||
request.setServerPort(8080); |
|
||||||
response = new MockHttpServletResponse(); |
|
||||||
ep.setPortResolver(new MockPortResolver(8080, 8443)); |
|
||||||
ep.commence(request, response); |
|
||||||
assertEquals("https://www.example.com:8443/bigWebApp/hello", response.getRedirectedUrl()); |
|
||||||
|
|
||||||
// Now test an unusual custom HTTP:HTTPS is handled properly
|
|
||||||
request.setServerPort(8888); |
|
||||||
response = new MockHttpServletResponse(); |
|
||||||
ep.commence(request, response); |
|
||||||
assertEquals("https://www.example.com:8443/bigWebApp/hello", response.getRedirectedUrl()); |
|
||||||
|
|
||||||
PortMapperImpl portMapper = new PortMapperImpl(); |
|
||||||
Map map = new HashMap(); |
|
||||||
map.put("8888", "9999"); |
|
||||||
portMapper.setPortMappings(map); |
|
||||||
response = new MockHttpServletResponse(); |
|
||||||
|
|
||||||
ep = new CaptchaEntryPoint(); |
|
||||||
ep.setCaptchaFormUrl("/hello"); |
|
||||||
ep.setPortMapper(new PortMapperImpl()); |
|
||||||
ep.setForceHttps(true); |
|
||||||
ep.setPortMapper(portMapper); |
|
||||||
ep.setPortResolver(new MockPortResolver(8888, 9999)); |
|
||||||
ep.setIncludeOriginalRequest(false); |
|
||||||
|
|
||||||
ep.afterPropertiesSet(); |
|
||||||
|
|
||||||
ep.commence(request, response); |
|
||||||
assertEquals("https://www.example.com:9999/bigWebApp/hello", response.getRedirectedUrl()); |
|
||||||
} |
|
||||||
|
|
||||||
public void testHttpsOperationFromOriginalHttpsUrl() |
|
||||||
throws Exception { |
|
||||||
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(); |
|
||||||
|
|
||||||
CaptchaEntryPoint ep = new CaptchaEntryPoint(); |
|
||||||
ep.setIncludeOriginalRequest(false); |
|
||||||
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); |
|
||||||
assertEquals("https://www.example.com/bigWebApp/hello", response.getRedirectedUrl()); |
|
||||||
|
|
||||||
request.setServerPort(8443); |
|
||||||
response = new MockHttpServletResponse(); |
|
||||||
ep.setPortResolver(new MockPortResolver(8080, 8443)); |
|
||||||
ep.commence(request, response); |
|
||||||
assertEquals("https://www.example.com:8443/bigWebApp/hello", response.getRedirectedUrl()); |
|
||||||
} |
|
||||||
|
|
||||||
public void testNormalOperation() throws Exception { |
|
||||||
CaptchaEntryPoint ep = new CaptchaEntryPoint(); |
|
||||||
ep.setCaptchaFormUrl("/hello"); |
|
||||||
ep.setPortMapper(new PortMapperImpl()); |
|
||||||
ep.setPortResolver(new MockPortResolver(80, 443)); |
|
||||||
ep.afterPropertiesSet(); |
|
||||||
ep.setIncludeOriginalRequest(false); |
|
||||||
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.setRequestURI("/some_path"); |
|
||||||
request.setContextPath("/bigWebApp"); |
|
||||||
request.setScheme("http"); |
|
||||||
request.setServerName("www.example.com"); |
|
||||||
request.setContextPath("/bigWebApp"); |
|
||||||
request.setServerPort(80); |
|
||||||
|
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse(); |
|
||||||
|
|
||||||
ep.afterPropertiesSet(); |
|
||||||
ep.commence(request, response); |
|
||||||
assertEquals("http://www.example.com/bigWebApp/hello", response.getRedirectedUrl()); |
|
||||||
} |
|
||||||
|
|
||||||
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.setIncludeOriginalRequest(false); |
|
||||||
|
|
||||||
ep.afterPropertiesSet(); |
|
||||||
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.setRequestURI("/some_path"); |
|
||||||
request.setContextPath("/bigWebApp"); |
|
||||||
request.setScheme("http"); |
|
||||||
request.setServerName("www.example.com"); |
|
||||||
request.setContextPath("/bigWebApp"); |
|
||||||
request.setServerPort(8888); // NB: Port we can't resolve
|
|
||||||
|
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse(); |
|
||||||
|
|
||||||
ep.afterPropertiesSet(); |
|
||||||
ep.commence(request, response); |
|
||||||
|
|
||||||
// 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()); |
|
||||||
} |
|
||||||
|
|
||||||
public void testOperationWithOriginalRequestIncludes() |
|
||||||
throws Exception { |
|
||||||
CaptchaEntryPoint ep = new CaptchaEntryPoint(); |
|
||||||
ep.setCaptchaFormUrl("/hello"); |
|
||||||
|
|
||||||
PortMapperImpl mapper = new PortMapperImpl(); |
|
||||||
mapper.getTranslatedPortMappings().put(new Integer(8888), new Integer(1234)); |
|
||||||
ep.setPortMapper(mapper); |
|
||||||
|
|
||||||
ep.setPortResolver(new MockPortResolver(8888, 1234)); |
|
||||||
ep.setIncludeOriginalRequest(true); |
|
||||||
ep.afterPropertiesSet(); |
|
||||||
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.setMethod("post"); |
|
||||||
request.setRequestURI("/some_path"); |
|
||||||
request.setScheme("http"); |
|
||||||
request.setServerName("www.example.com"); |
|
||||||
|
|
||||||
// request.setContextPath("/bigWebApp");
|
|
||||||
// TODO correct this when the getRequestUrl from mock works...
|
|
||||||
request.setServerPort(8888); // NB: Port we can't resolve
|
|
||||||
|
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse(); |
|
||||||
|
|
||||||
ep.afterPropertiesSet(); |
|
||||||
ep.commence(request, response); |
|
||||||
assertEquals("http://www.example.com:8888/hello?original_requestUrl=" |
|
||||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8") + "&original_request_method=post", |
|
||||||
response.getRedirectedUrl()); |
|
||||||
|
|
||||||
// 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()); |
|
||||||
|
|
||||||
// test the multiple query params
|
|
||||||
ep.setIncludeOriginalParameters(true); |
|
||||||
|
|
||||||
request.addParameter("name", "value"); |
|
||||||
request.addParameter("name1", "value2"); |
|
||||||
response = new MockHttpServletResponse(); |
|
||||||
ep.commence(request, response); |
|
||||||
assertEquals("http://www.example.com:8888/hello?original_requestUrl=" |
|
||||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8") + "&original_request_method=post" |
|
||||||
+ "&original_request_parameters=" + URLEncoder.encode("name__value;;name1__value2", "UTF-8"), |
|
||||||
response.getRedirectedUrl()); |
|
||||||
|
|
||||||
// test add parameter to captcha form url??
|
|
||||||
ep.setCaptchaFormUrl("/hello?toto=titi"); |
|
||||||
response = new MockHttpServletResponse(); |
|
||||||
ep.commence(request, response); |
|
||||||
assertEquals("http://www.example.com:8888/hello?toto=titi&original_requestUrl=" |
|
||||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8") + "&original_request_method=post" |
|
||||||
+ "&original_request_parameters=" + URLEncoder.encode("name__value;;name1__value2", "UTF-8"), |
|
||||||
response.getRedirectedUrl()); |
|
||||||
|
|
||||||
// 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()); |
|
||||||
} |
|
||||||
|
|
||||||
public void testOperationWithOutsideWebApp() throws Exception { |
|
||||||
CaptchaEntryPoint ep = new CaptchaEntryPoint(); |
|
||||||
ep.setCaptchaFormUrl("https://www.jcaptcha.net/dotest/"); |
|
||||||
|
|
||||||
PortMapperImpl mapper = new PortMapperImpl(); |
|
||||||
mapper.getTranslatedPortMappings().put(new Integer(8888), new Integer(1234)); |
|
||||||
ep.setPortMapper(mapper); |
|
||||||
|
|
||||||
ep.setPortResolver(new MockPortResolver(8888, 1234)); |
|
||||||
ep.setIncludeOriginalRequest(true); |
|
||||||
ep.setOutsideWebApp(true); |
|
||||||
|
|
||||||
ep.afterPropertiesSet(); |
|
||||||
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.setRequestURI("/some_path"); |
|
||||||
request.setScheme("http"); |
|
||||||
request.setServerName("www.example.com"); |
|
||||||
request.setMethod("post"); |
|
||||||
|
|
||||||
// request.setContextPath("/bigWebApp");
|
|
||||||
// TODO correct this when the getRequestUrl from mock works...
|
|
||||||
request.setServerPort(8888); // NB: Port we can't resolve
|
|
||||||
|
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse(); |
|
||||||
|
|
||||||
ep.afterPropertiesSet(); |
|
||||||
ep.commence(request, response); |
|
||||||
assertEquals("https://www.jcaptcha.net/dotest/?original_requestUrl=" |
|
||||||
+ URLEncoder.encode("http://www.example.com:8888/some_path", "UTF-8") + "&original_request_method=post", |
|
||||||
response.getRedirectedUrl()); |
|
||||||
|
|
||||||
// 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()); |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,106 +0,0 @@ |
|||||||
/* Copyright 2004, 2005, 2006 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 org.springframework.security.captcha; |
|
||||||
|
|
||||||
import junit.framework.TestCase; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Tests {@link CaptchaSecurityContextImpl}. |
|
||||||
* |
|
||||||
* @author marc antoine Garrigue |
|
||||||
* @version $Id$ |
|
||||||
*/ |
|
||||||
public class CaptchaSecurityContextImplTests extends TestCase { |
|
||||||
//~ Methods ========================================================================================================
|
|
||||||
|
|
||||||
public void testDefaultValues() { |
|
||||||
CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); |
|
||||||
assertEquals("should not be human", false, context.isHuman()); |
|
||||||
assertEquals("should be 0", 0, context.getLastPassedCaptchaDateInMillis()); |
|
||||||
assertEquals("should be 0", 0, context.getHumanRestrictedResourcesRequestsCount()); |
|
||||||
} |
|
||||||
|
|
||||||
public void testEquals() { |
|
||||||
CaptchaSecurityContext context1 = new CaptchaSecurityContextImpl(); |
|
||||||
CaptchaSecurityContext context2 = new CaptchaSecurityContextImpl(); |
|
||||||
|
|
||||||
assertEquals(context1, context2); |
|
||||||
|
|
||||||
assertFalse(context1.isHuman()); |
|
||||||
context1.setHuman(); |
|
||||||
assertNotSame(context1, context2); |
|
||||||
|
|
||||||
// Get fresh copy
|
|
||||||
context1 = new CaptchaSecurityContextImpl(); |
|
||||||
assertEquals(context1, context2); |
|
||||||
|
|
||||||
context1.incrementHumanRestrictedResourcesRequestsCount(); |
|
||||||
assertNotSame(context1, context2); |
|
||||||
} |
|
||||||
|
|
||||||
public void testHashcode() { |
|
||||||
CaptchaSecurityContext context1 = new CaptchaSecurityContextImpl(); |
|
||||||
CaptchaSecurityContext context2 = new CaptchaSecurityContextImpl(); |
|
||||||
|
|
||||||
assertEquals(context1.hashCode(), context2.hashCode()); |
|
||||||
|
|
||||||
assertFalse(context1.isHuman()); |
|
||||||
context1.setHuman(); |
|
||||||
assertTrue(context1.hashCode() != context2.hashCode()); |
|
||||||
|
|
||||||
// Get fresh copy
|
|
||||||
context1 = new CaptchaSecurityContextImpl(); |
|
||||||
assertEquals(context1.hashCode(), context2.hashCode()); |
|
||||||
|
|
||||||
context1.incrementHumanRestrictedResourcesRequestsCount(); |
|
||||||
assertTrue(context1 != context2); |
|
||||||
} |
|
||||||
|
|
||||||
public void testIncrementRequests() { |
|
||||||
CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); |
|
||||||
context.setHuman(); |
|
||||||
assertEquals("should be human", true, context.isHuman()); |
|
||||||
assertEquals("should be 0", 0, context.getHumanRestrictedResourcesRequestsCount()); |
|
||||||
context.incrementHumanRestrictedResourcesRequestsCount(); |
|
||||||
assertEquals("should be 1", 1, context.getHumanRestrictedResourcesRequestsCount()); |
|
||||||
} |
|
||||||
|
|
||||||
public void testResetHuman() { |
|
||||||
CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); |
|
||||||
context.setHuman(); |
|
||||||
assertEquals("should be human", true, context.isHuman()); |
|
||||||
assertEquals("should be 0", 0, context.getHumanRestrictedResourcesRequestsCount()); |
|
||||||
context.incrementHumanRestrictedResourcesRequestsCount(); |
|
||||||
assertEquals("should be 1", 1, context.getHumanRestrictedResourcesRequestsCount()); |
|
||||||
|
|
||||||
long now = System.currentTimeMillis(); |
|
||||||
context.setHuman(); |
|
||||||
assertEquals("should be 0", 0, context.getHumanRestrictedResourcesRequestsCount()); |
|
||||||
assertTrue("should be more than 0", (context.getLastPassedCaptchaDateInMillis() - now) >= 0); |
|
||||||
assertTrue("should be less than 0,1 seconde", (context.getLastPassedCaptchaDateInMillis() - now) < 100); |
|
||||||
} |
|
||||||
|
|
||||||
public void testSetHuman() { |
|
||||||
CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); |
|
||||||
long now = System.currentTimeMillis(); |
|
||||||
context.setHuman(); |
|
||||||
assertEquals("should be human", true, context.isHuman()); |
|
||||||
assertTrue("should be more than 0", (context.getLastPassedCaptchaDateInMillis() - now) >= 0); |
|
||||||
assertTrue("should be less than 0,1 seconde", (context.getLastPassedCaptchaDateInMillis() - now) < 100); |
|
||||||
assertEquals("should be 0", 0, context.getHumanRestrictedResourcesRequestsCount()); |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,115 +0,0 @@ |
|||||||
/* Copyright 2004, 2005, 2006 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 org.springframework.security.captcha; |
|
||||||
|
|
||||||
import junit.framework.TestCase; |
|
||||||
|
|
||||||
import org.springframework.security.context.SecurityContextHolder; |
|
||||||
|
|
||||||
import org.springframework.security.util.MockFilter; |
|
||||||
import org.springframework.security.util.MockFilterChain; |
|
||||||
|
|
||||||
import org.springframework.mock.web.MockHttpServletRequest; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Tests {@link CaptchaValidationProcessingFilter}. |
|
||||||
* |
|
||||||
* @author marc antoine Garrigue |
|
||||||
* @version $Id$ |
|
||||||
*/ |
|
||||||
public class CaptchaValidationProcessingFilterTests extends TestCase { |
|
||||||
//~ Methods ========================================================================================================
|
|
||||||
|
|
||||||
/* |
|
||||||
*/ |
|
||||||
public void testAfterPropertiesSet() throws Exception { |
|
||||||
CaptchaValidationProcessingFilter filter = new CaptchaValidationProcessingFilter(); |
|
||||||
|
|
||||||
try { |
|
||||||
filter.afterPropertiesSet(); |
|
||||||
fail("should have thrown an invalid argument exception"); |
|
||||||
} catch (Exception e) { |
|
||||||
assertTrue("should be an InvalidArgumentException", |
|
||||||
IllegalArgumentException.class.isAssignableFrom(e.getClass())); |
|
||||||
} |
|
||||||
|
|
||||||
filter.setCaptchaService(new MockCaptchaServiceProxy()); |
|
||||||
filter.afterPropertiesSet(); |
|
||||||
filter.setCaptchaValidationParameter(null); |
|
||||||
|
|
||||||
try { |
|
||||||
filter.afterPropertiesSet(); |
|
||||||
fail("should have thrown an invalid argument exception"); |
|
||||||
} catch (Exception e) { |
|
||||||
assertTrue("should be an InvalidArgumentException", |
|
||||||
IllegalArgumentException.class.isAssignableFrom(e.getClass())); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/* |
|
||||||
* Test method for |
|
||||||
* 'org.springframework.security.captcha.CaptchaValidationProcessingFilter.doFilter(ServletRequest, |
|
||||||
* ServletResponse, FilterChain)' |
|
||||||
*/ |
|
||||||
public void testDoFilterWithRequestParameter() throws Exception { |
|
||||||
CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); |
|
||||||
SecurityContextHolder.setContext(context); |
|
||||||
|
|
||||||
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()); |
|
||||||
} |
|
||||||
|
|
||||||
/* |
|
||||||
* Test method for |
|
||||||
* 'org.springframework.security.captcha.CaptchaValidationProcessingFilter.doFilter(ServletRequest, |
|
||||||
* ServletResponse, FilterChain)' |
|
||||||
*/ |
|
||||||
public void testDoFilterWithoutRequestParameter() throws Exception { |
|
||||||
CaptchaSecurityContext context = new CaptchaSecurityContextImpl(); |
|
||||||
SecurityContextHolder.setContext(context); |
|
||||||
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
CaptchaValidationProcessingFilter filter = new CaptchaValidationProcessingFilter(); |
|
||||||
MockCaptchaServiceProxy service = new MockCaptchaServiceProxy(); |
|
||||||
MockFilterChain chain = new MockFilterChain(true); |
|
||||||
filter.setCaptchaService(service); |
|
||||||
filter.doFilter(request, null, chain); |
|
||||||
assertFalse("proxy should not have been called", service.hasBeenCalled); |
|
||||||
assertFalse("context should not have been updated", context.isHuman()); |
|
||||||
|
|
||||||
// test with valid
|
|
||||||
service.valid = true; |
|
||||||
filter.doFilter(request, null, chain); |
|
||||||
assertFalse("proxy should not have been called", service.hasBeenCalled); |
|
||||||
assertFalse("context should not have been updated", context.isHuman()); |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,35 +0,0 @@ |
|||||||
/* Copyright 2004, 2005, 2006 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 org.springframework.security.captcha; |
|
||||||
|
|
||||||
/** |
|
||||||
* @author Marc-Antoine Garrigue |
|
||||||
* @version $Id$ |
|
||||||
*/ |
|
||||||
public class MockCaptchaServiceProxy implements CaptchaServiceProxy { |
|
||||||
//~ Instance fields ================================================================================================
|
|
||||||
|
|
||||||
public boolean hasBeenCalled = false; |
|
||||||
public boolean valid = false; |
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
|
||||||
|
|
||||||
public boolean validateReponseForId(String id, Object response) { |
|
||||||
hasBeenCalled = true; |
|
||||||
|
|
||||||
return valid; |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,72 +0,0 @@ |
|||||||
/* Copyright 2004, 2005, 2006 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 org.springframework.security.captcha; |
|
||||||
|
|
||||||
import junit.framework.*; |
|
||||||
|
|
||||||
import org.springframework.security.captcha.TestOnceAfterMaxRequestsCaptchaChannelProcessor; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* |
|
||||||
* @author Marc-Antoine Garrigue |
|
||||||
* @version $Revision: 2142 $ |
|
||||||
*/ |
|
||||||
public class TestOnceAfterMaxRequestsCaptchaChannelProcessorTests extends TestCase { |
|
||||||
//~ Instance fields ================================================================================================
|
|
||||||
|
|
||||||
TestOnceAfterMaxRequestsCaptchaChannelProcessor testOnceAfterMaxRequestsCaptchaChannelProcessor; |
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
|
||||||
|
|
||||||
protected void setUp() throws Exception { |
|
||||||
super.setUp(); |
|
||||||
testOnceAfterMaxRequestsCaptchaChannelProcessor = new TestOnceAfterMaxRequestsCaptchaChannelProcessor(); |
|
||||||
} |
|
||||||
|
|
||||||
public void testIsContextValidConcerningHumanity() |
|
||||||
throws Exception { |
|
||||||
testOnceAfterMaxRequestsCaptchaChannelProcessor.setThreshold(1); |
|
||||||
|
|
||||||
CaptchaSecurityContextImpl context = new CaptchaSecurityContextImpl(); |
|
||||||
assertTrue(testOnceAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); |
|
||||||
|
|
||||||
context.incrementHumanRestrictedResourcesRequestsCount(); |
|
||||||
|
|
||||||
testOnceAfterMaxRequestsCaptchaChannelProcessor.setThreshold(-1); |
|
||||||
assertFalse(testOnceAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); |
|
||||||
|
|
||||||
testOnceAfterMaxRequestsCaptchaChannelProcessor.setThreshold(3); |
|
||||||
assertTrue(testOnceAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); |
|
||||||
context.incrementHumanRestrictedResourcesRequestsCount(); |
|
||||||
assertTrue(testOnceAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); |
|
||||||
context.incrementHumanRestrictedResourcesRequestsCount(); |
|
||||||
assertFalse(testOnceAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); |
|
||||||
context.setHuman(); |
|
||||||
|
|
||||||
for (int i = 0; i < (2 * testOnceAfterMaxRequestsCaptchaChannelProcessor.getThreshold()); i++) { |
|
||||||
assertTrue(testOnceAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void testNewContext() { |
|
||||||
CaptchaSecurityContextImpl context = new CaptchaSecurityContextImpl(); |
|
||||||
|
|
||||||
assertFalse(testOnceAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); |
|
||||||
testOnceAfterMaxRequestsCaptchaChannelProcessor.setThreshold(1); |
|
||||||
assertTrue(testOnceAfterMaxRequestsCaptchaChannelProcessor.isContextValidConcerningHumanity(context)); |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,23 +0,0 @@ |
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> |
|
||||||
<modelVersion>4.0.0</modelVersion> |
|
||||||
<parent> |
|
||||||
<groupId>org.springframework.security</groupId> |
|
||||||
<artifactId>spring-security-sandbox</artifactId> |
|
||||||
<version>3.0.0.CI-SNAPSHOT</version> |
|
||||||
</parent> |
|
||||||
<artifactId>spring-security-webwork</artifactId> |
|
||||||
<name>Spring Security - Webwork support</name> |
|
||||||
<description>Spring Security - Support for WebWork 2</description> |
|
||||||
|
|
||||||
<dependencies> |
|
||||||
<dependency> |
|
||||||
<groupId>opensymphony</groupId> |
|
||||||
<artifactId>webwork</artifactId> |
|
||||||
<version>2.2.3</version> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>javax.servlet</groupId> |
|
||||||
<artifactId>servlet-api</artifactId> |
|
||||||
</dependency> |
|
||||||
</dependencies> |
|
||||||
</project> |
|
||||||
@ -1,132 +0,0 @@ |
|||||||
/* Copyright 2006 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 org.springframework.security.webwork; |
|
||||||
|
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
import javax.servlet.ServletContext; |
|
||||||
import javax.servlet.ServletException; |
|
||||||
import javax.servlet.http.HttpServletRequest; |
|
||||||
import javax.servlet.http.HttpServletResponse; |
|
||||||
|
|
||||||
import org.springframework.security.ui.ExceptionTranslationFilter; |
|
||||||
import org.apache.commons.logging.Log; |
|
||||||
import org.apache.commons.logging.LogFactory; |
|
||||||
|
|
||||||
import com.opensymphony.webwork.ServletActionContext; |
|
||||||
import com.opensymphony.webwork.dispatcher.DispatcherUtils; |
|
||||||
import com.opensymphony.webwork.dispatcher.mapper.ActionMapping; |
|
||||||
import com.opensymphony.xwork.ActionContext; |
|
||||||
import com.opensymphony.xwork.ActionProxy; |
|
||||||
import com.opensymphony.xwork.ActionProxyFactory; |
|
||||||
import com.opensymphony.xwork.Result; |
|
||||||
import com.opensymphony.xwork.config.ConfigurationException; |
|
||||||
import com.opensymphony.xwork.util.OgnlValueStack; |
|
||||||
import com.opensymphony.xwork.util.XWorkContinuationConfig; |
|
||||||
|
|
||||||
/** |
|
||||||
* <p> |
|
||||||
* WebWork {@link DispatcherUtils} that ignores Acegi exceptions so they can be processed by |
|
||||||
* {@link ExceptionTranslationFilter}. |
|
||||||
* </p> |
|
||||||
* |
|
||||||
* <p> |
|
||||||
* This is meant to be fixed inside WebWork, see <a href="http://jira.opensymphony.com/browse/WW-291">WW-291</a>. Known |
|
||||||
* broken versions are 2.2.3 and 2.2.4. |
|
||||||
* </p> |
|
||||||
* |
|
||||||
* @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a> |
|
||||||
* @version $Id$ |
|
||||||
*/ |
|
||||||
public class AcegiDispatcherUtils extends DispatcherUtils { |
|
||||||
|
|
||||||
private static final Log LOG = LogFactory.getLog(AcegiDispatcherUtils.class); |
|
||||||
|
|
||||||
protected AcegiDispatcherUtils(ServletContext servletContext) { |
|
||||||
super(servletContext); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* <p> |
|
||||||
* Loads the action and executes it. This method first creates the action context from the given parameters then |
|
||||||
* loads an <tt>ActionProxy</tt> from the given action name and namespace. After that, the action is executed and |
|
||||||
* output channels throught the response object. Actions not found are sent back to the user via the |
|
||||||
* {@link DispatcherUtils#sendError} method, using the 404 return code. All other errors are reported by throwing a |
|
||||||
* ServletException. |
|
||||||
* </p> |
|
||||||
* |
|
||||||
* <p> |
|
||||||
* Difference between this and WebWork prvided class is that any unhandled exception will be thrown instead of |
|
||||||
* processed inside WebWork. |
|
||||||
* </p> |
|
||||||
* |
|
||||||
* @param request the HttpServletRequest object |
|
||||||
* @param response the HttpServletResponse object |
|
||||||
* @param mapping the action mapping object |
|
||||||
* @throws ServletException when an unknown error occurs (not a 404, but typically something that would end up as a |
|
||||||
* 5xx by the servlet container) |
|
||||||
*/ |
|
||||||
public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context, |
|
||||||
ActionMapping mapping) throws ServletException { |
|
||||||
Map extraContext = createContextMap(request, response, mapping, context); |
|
||||||
|
|
||||||
// If there was a previous value stack, then create a new copy and pass it in to be used by the new Action
|
|
||||||
OgnlValueStack stack = (OgnlValueStack) request.getAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY); |
|
||||||
if (stack != null) { |
|
||||||
extraContext.put(ActionContext.VALUE_STACK, new OgnlValueStack(stack)); |
|
||||||
} |
|
||||||
|
|
||||||
try { |
|
||||||
String namespace = mapping.getNamespace(); |
|
||||||
String name = mapping.getName(); |
|
||||||
String method = mapping.getMethod(); |
|
||||||
|
|
||||||
String id = request.getParameter(XWorkContinuationConfig.CONTINUE_PARAM); |
|
||||||
if (id != null) { |
|
||||||
// remove the continue key from the params - we don't want to bother setting
|
|
||||||
// on the value stack since we know it won't work. Besides, this breaks devMode!
|
|
||||||
Map params = (Map) extraContext.get(ActionContext.PARAMETERS); |
|
||||||
params.remove(XWorkContinuationConfig.CONTINUE_PARAM); |
|
||||||
|
|
||||||
// and now put the key in the context to be picked up later by XWork
|
|
||||||
extraContext.put(XWorkContinuationConfig.CONTINUE_KEY, id); |
|
||||||
} |
|
||||||
|
|
||||||
ActionProxy proxy = ActionProxyFactory.getFactory().createActionProxy(namespace, name, extraContext, true, |
|
||||||
false); |
|
||||||
proxy.setMethod(method); |
|
||||||
request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY, proxy.getInvocation().getStack()); |
|
||||||
|
|
||||||
// if the ActionMapping says to go straight to a result, do it!
|
|
||||||
if (mapping.getResult() != null) { |
|
||||||
Result result = mapping.getResult(); |
|
||||||
result.execute(proxy.getInvocation()); |
|
||||||
} else { |
|
||||||
proxy.execute(); |
|
||||||
} |
|
||||||
|
|
||||||
// If there was a previous value stack then set it back onto the request
|
|
||||||
if (stack != null) { |
|
||||||
request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY, stack); |
|
||||||
} |
|
||||||
} catch (ConfigurationException e) { |
|
||||||
LOG.error("Could not find action", e); |
|
||||||
sendError(request, response, context, HttpServletResponse.SC_NOT_FOUND, e); |
|
||||||
} catch (Exception e) { |
|
||||||
throw new ServletException(e); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,49 +0,0 @@ |
|||||||
/* Copyright 2006 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 org.springframework.security.webwork; |
|
||||||
|
|
||||||
import javax.servlet.FilterConfig; |
|
||||||
import javax.servlet.ServletException; |
|
||||||
|
|
||||||
import org.springframework.security.ui.ExceptionTranslationFilter; |
|
||||||
|
|
||||||
import com.opensymphony.webwork.dispatcher.DispatcherUtils; |
|
||||||
|
|
||||||
/** |
|
||||||
* <p> |
|
||||||
* {@link com.opensymphony.webwork.dispatcher.FilterDispatcher} that will setup WebWork to ignore Acegi exceptions so |
|
||||||
* they can be processed by {@link ExceptionTranslationFilter} |
|
||||||
* </p> |
|
||||||
* |
|
||||||
* <p> |
|
||||||
* Set it up in your web.xml instead of WebWork provided {@link com.opensymphony.webwork.dispatcher.FilterDispatcher}. |
|
||||||
* </p> |
|
||||||
* |
|
||||||
* <p> |
|
||||||
* This is meant to be fixed inside WebWork, see <a href="http://jira.opensymphony.com/browse/WW-291">WW-291</a>. Known |
|
||||||
* broken versions are 2.2.3 and 2.2.4. |
|
||||||
* </p> |
|
||||||
* |
|
||||||
* @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a> |
|
||||||
* @version $Id$ |
|
||||||
*/ |
|
||||||
public class FilterDispatcher extends com.opensymphony.webwork.dispatcher.FilterDispatcher { |
|
||||||
|
|
||||||
public void init(FilterConfig filterConfig) throws ServletException { |
|
||||||
super.init(filterConfig); |
|
||||||
DispatcherUtils.setInstance(new AcegiDispatcherUtils(filterConfig.getServletContext())); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
Loading…
Reference in new issue