Make ChannelDecisionManagerImpl iterate through a list of channel security processors.
This commit is contained in:
@@ -15,12 +15,23 @@
|
||||
|
||||
package net.sf.acegisecurity.securechannel;
|
||||
|
||||
import net.sf.acegisecurity.ConfigAttribute;
|
||||
import net.sf.acegisecurity.ConfigAttributeDefinition;
|
||||
import net.sf.acegisecurity.intercept.web.FilterInvocation;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
|
||||
/**
|
||||
* Decides whether a web channel provides sufficient security.
|
||||
*
|
||||
* <P>
|
||||
* If necessary due to the nature of the redirection, implementations should
|
||||
* store the original destination of the request in {@link
|
||||
* net.sf.acegisecurity.ui.AbstractProcessingFilter#ACEGI_SECURITY_TARGET_URL_KEY}.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
@@ -34,6 +45,23 @@ public interface ChannelDecisionManager {
|
||||
* ConfigAttributeDefinition}.
|
||||
*/
|
||||
public void decide(FilterInvocation invocation,
|
||||
ConfigAttributeDefinition config)
|
||||
throws InsecureChannelRequiredException, SecureChannelRequiredException;
|
||||
ConfigAttributeDefinition config) throws IOException, ServletException;
|
||||
|
||||
/**
|
||||
* Indicates whether this <code>ChannelDecisionManager</code> is able to
|
||||
* process the passed <code>ConfigAttribute</code>.
|
||||
*
|
||||
* <p>
|
||||
* This allows the <code>ChannelProcessingFilter</code> to check every
|
||||
* configuration attribute can be consumed by the configured
|
||||
* <code>ChannelDecisionManager</code>.
|
||||
* </p>
|
||||
*
|
||||
* @param attribute a configuration attribute that has been configured
|
||||
* against the <code>ChannelProcessingFilter</code>
|
||||
*
|
||||
* @return true if this <code>ChannelDecisionManager</code> can support the
|
||||
* passed configuration attribute
|
||||
*/
|
||||
public boolean supports(ConfigAttribute attribute);
|
||||
}
|
||||
|
||||
+67
-63
@@ -21,100 +21,104 @@ import net.sf.acegisecurity.intercept.web.FilterInvocation;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of {@link ChannelDecisionManager}.
|
||||
*
|
||||
* <p>
|
||||
* Ensures configuration attribute requested channel security is present by
|
||||
* review of <code>HttpServletRequest.isSecure()</code> responses.
|
||||
* Iterates through each configured {@link ChannelProcessor}. If a
|
||||
* <code>ChannelProcessor</code> has any issue with the security of the
|
||||
* request, it should cause a redirect, exception or whatever other action is
|
||||
* appropriate for the <code>ChannelProcessor</code> implementation.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* The class responds to two and only two case-sensitive keywords: {@link
|
||||
* #getInsecureKeyword()} and {@link #getSecureKeyword}. If either of these
|
||||
* keywords are detected, <code>HttpServletRequest.isSecure()</code> is used
|
||||
* to determine the channel security offered. If the channel security differs
|
||||
* from that requested by the keyword, the relevant exception is thrown.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* If both the <code>secureKeyword</code> and <code>insecureKeyword</code>
|
||||
* configuration attributes are detected, the request will be deemed to be
|
||||
* requesting a secure channel. This is a reasonable approach, as when in
|
||||
* doubt, the decision manager assumes the most secure outcome is desired. Of
|
||||
* course, you <b>should</b> indicate one configuration attribute or the other
|
||||
* (not both).
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* The default <code>secureKeyword</code> and <code>insecureKeyword</code> is
|
||||
* <code>REQUIRES_SECURE_CHANNEL</code> and
|
||||
* <code>REQUIRES_INSECURE_CHANNEL</code> respectively.
|
||||
* Once any response is committed (ie a redirect is written to the response
|
||||
* object), the <code>ChannelDecisionManagerImpl</code> will not iterate
|
||||
* through any further <code>ChannelProcessor</code>s.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ChannelDecisionManagerImpl implements InitializingBean,
|
||||
ChannelDecisionManager {
|
||||
public class ChannelDecisionManagerImpl implements ChannelDecisionManager,
|
||||
InitializingBean {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private String insecureKeyword = "REQUIRES_INSECURE_CHANNEL";
|
||||
private String secureKeyword = "REQUIRES_SECURE_CHANNEL";
|
||||
private List channelProcessors;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setInsecureKeyword(String insecureKeyword) {
|
||||
this.insecureKeyword = insecureKeyword;
|
||||
public void setChannelProcessors(List newList) {
|
||||
checkIfValidList(newList);
|
||||
|
||||
Iterator iter = newList.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
Object currentObject = null;
|
||||
|
||||
try {
|
||||
currentObject = iter.next();
|
||||
|
||||
ChannelProcessor attemptToCast = (ChannelProcessor) currentObject;
|
||||
} catch (ClassCastException cce) {
|
||||
throw new IllegalArgumentException("ChannelProcessor "
|
||||
+ currentObject.getClass().getName()
|
||||
+ " must implement ChannelProcessor");
|
||||
}
|
||||
}
|
||||
|
||||
this.channelProcessors = newList;
|
||||
}
|
||||
|
||||
public String getInsecureKeyword() {
|
||||
return insecureKeyword;
|
||||
}
|
||||
|
||||
public void setSecureKeyword(String secureKeyword) {
|
||||
this.secureKeyword = secureKeyword;
|
||||
}
|
||||
|
||||
public String getSecureKeyword() {
|
||||
return secureKeyword;
|
||||
public List getChannelProcessors() {
|
||||
return this.channelProcessors;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if ((secureKeyword == null) || "".equals(secureKeyword)) {
|
||||
throw new IllegalArgumentException("secureKeyword required");
|
||||
}
|
||||
|
||||
if ((insecureKeyword == null) || "".equals(insecureKeyword)) {
|
||||
throw new IllegalArgumentException("insecureKeyword required");
|
||||
}
|
||||
checkIfValidList(this.channelProcessors);
|
||||
}
|
||||
|
||||
public void decide(FilterInvocation invocation,
|
||||
ConfigAttributeDefinition config) throws SecureChannelRequiredException {
|
||||
if ((invocation == null) || (config == null)) {
|
||||
throw new IllegalArgumentException("Nulls cannot be provided");
|
||||
}
|
||||
|
||||
Iterator iter = config.getConfigAttributes();
|
||||
ConfigAttributeDefinition config) throws IOException, ServletException {
|
||||
Iterator iter = this.channelProcessors.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
ConfigAttribute attribute = (ConfigAttribute) iter.next();
|
||||
ChannelProcessor processor = (ChannelProcessor) iter.next();
|
||||
|
||||
if (attribute.equals(secureKeyword)) {
|
||||
if (!invocation.getHttpRequest().isSecure()) {
|
||||
throw new SecureChannelRequiredException(
|
||||
"Request is not being made over a secure channel");
|
||||
}
|
||||
}
|
||||
processor.decide(invocation, config);
|
||||
|
||||
if (attribute.equals(insecureKeyword)) {
|
||||
if (invocation.getHttpRequest().isSecure()) {
|
||||
throw new InsecureChannelRequiredException(
|
||||
"Request is being made over a secure channel when an insecure channel is required");
|
||||
}
|
||||
if (invocation.getResponse().isCommitted()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
Iterator iter = this.channelProcessors.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
ChannelProcessor processor = (ChannelProcessor) iter.next();
|
||||
|
||||
if (processor.supports(attribute)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void checkIfValidList(List listToCheck) {
|
||||
if ((listToCheck == null) || (listToCheck.size() == 0)) {
|
||||
throw new IllegalArgumentException(
|
||||
"A list of ChannelProcessors is required");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,11 +23,13 @@ import javax.servlet.ServletResponse;
|
||||
|
||||
|
||||
/**
|
||||
* Used by {@link ChannelProcessingFilter} to launch a web channel.
|
||||
* May be used by a {@link ChannelProcessor} to launch a web channel.
|
||||
*
|
||||
* <P>
|
||||
* Depending on the implementation, a secure or insecure channel will be
|
||||
* launched.
|
||||
* <code>ChannelProcessor</code>s can elect to launch a new web channel
|
||||
* directly, or they can delegate to another class. The
|
||||
* <code>ChannelEntryPoint</code> is a pluggable interface to assist
|
||||
* <code>ChannelProcessor</code>s in performing this delegation.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
@@ -42,13 +44,10 @@ public interface ChannelEntryPoint {
|
||||
* <P>
|
||||
* Implementations should modify the headers on the
|
||||
* <code>ServletResponse</code> as necessary to commence the user agent
|
||||
* using the implementation's supported channel type (ie secure or
|
||||
* insecure).
|
||||
* using the implementation's supported channel type.
|
||||
* </p>
|
||||
*
|
||||
* @param request that resulted in a
|
||||
* <code>SecureChannelRequiredException</code> or
|
||||
* <code>InsecureChannelRequiredException</code>
|
||||
* @param request that a <code>ChannelProcessor</code> has rejected
|
||||
* @param response so that the user agent can begin using a new channel
|
||||
*/
|
||||
public void commence(ServletRequest request, ServletResponse response)
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
package net.sf.acegisecurity.securechannel;
|
||||
|
||||
import net.sf.acegisecurity.ConfigAttribute;
|
||||
import net.sf.acegisecurity.ConfigAttributeDefinition;
|
||||
import net.sf.acegisecurity.intercept.web.FilterInvocation;
|
||||
import net.sf.acegisecurity.intercept.web.FilterInvocationDefinitionSource;
|
||||
@@ -26,6 +27,10 @@ import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
@@ -46,6 +51,12 @@ import javax.servlet.http.HttpServletResponse;
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* Delegates the actual channel security decisions and necessary actions to the
|
||||
* configured {@link ChannelDecisionManager}. If a response is committed by
|
||||
* the <code>ChannelDecisionManager</code>, the filter chain will not proceed.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* <B>Do not use this class directly.</B> Instead configure
|
||||
* <code>web.xml</code> to use the {@link
|
||||
* net.sf.acegisecurity.util.FilterToBeanProxy}.
|
||||
@@ -62,8 +73,6 @@ public class ChannelProcessingFilter implements InitializingBean, Filter {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private ChannelDecisionManager channelDecisionManager;
|
||||
private ChannelEntryPoint insecureChannelEntryPoint;
|
||||
private ChannelEntryPoint secureChannelEntryPoint;
|
||||
private FilterInvocationDefinitionSource filterInvocationDefinitionSource;
|
||||
|
||||
//~ Methods ================================================================
|
||||
@@ -86,23 +95,6 @@ public class ChannelProcessingFilter implements InitializingBean, Filter {
|
||||
return filterInvocationDefinitionSource;
|
||||
}
|
||||
|
||||
public void setInsecureChannelEntryPoint(
|
||||
ChannelEntryPoint insecureChannelEntryPoint) {
|
||||
this.insecureChannelEntryPoint = insecureChannelEntryPoint;
|
||||
}
|
||||
|
||||
public ChannelEntryPoint getInsecureChannelEntryPoint() {
|
||||
return insecureChannelEntryPoint;
|
||||
}
|
||||
|
||||
public void setSecureChannelEntryPoint(ChannelEntryPoint channelEntryPoint) {
|
||||
this.secureChannelEntryPoint = channelEntryPoint;
|
||||
}
|
||||
|
||||
public ChannelEntryPoint getSecureChannelEntryPoint() {
|
||||
return secureChannelEntryPoint;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (filterInvocationDefinitionSource == null) {
|
||||
throw new IllegalArgumentException(
|
||||
@@ -114,14 +106,41 @@ public class ChannelProcessingFilter implements InitializingBean, Filter {
|
||||
"channelDecisionManager must be specified");
|
||||
}
|
||||
|
||||
if (secureChannelEntryPoint == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"secureChannelEntryPoint must be specified");
|
||||
Iterator iter = this.filterInvocationDefinitionSource
|
||||
.getConfigAttributeDefinitions();
|
||||
|
||||
if (iter == null) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn(
|
||||
"Could not validate configuration attributes as the FilterInvocationDefinitionSource did not return a ConfigAttributeDefinition Iterator");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (insecureChannelEntryPoint == null) {
|
||||
Set set = new HashSet();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
ConfigAttributeDefinition def = (ConfigAttributeDefinition) iter
|
||||
.next();
|
||||
Iterator attributes = def.getConfigAttributes();
|
||||
|
||||
while (attributes.hasNext()) {
|
||||
ConfigAttribute attr = (ConfigAttribute) attributes.next();
|
||||
|
||||
if (!this.channelDecisionManager.supports(attr)) {
|
||||
set.add(attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (set.size() == 0) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Validated configuration attributes");
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"insecureChannelEntryPoint must be specified");
|
||||
"Unsupported configuration attributes: " + set.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,27 +166,9 @@ public class ChannelProcessingFilter implements InitializingBean, Filter {
|
||||
+ "; ConfigAttributes: " + attr.toString());
|
||||
}
|
||||
|
||||
try {
|
||||
channelDecisionManager.decide(fi, attr);
|
||||
} catch (SecureChannelRequiredException secureException) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Channel insufficient security ("
|
||||
+ secureException.getMessage()
|
||||
+ "); delegating to secureChannelEntryPoint");
|
||||
}
|
||||
|
||||
secureChannelEntryPoint.commence(request, response);
|
||||
|
||||
return;
|
||||
} catch (InsecureChannelRequiredException insecureException) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Channel too much security ("
|
||||
+ insecureException.getMessage()
|
||||
+ "); delegating to insecureChannelEntryPoint");
|
||||
}
|
||||
|
||||
insecureChannelEntryPoint.commence(request, response);
|
||||
channelDecisionManager.decide(fi, attr);
|
||||
|
||||
if (fi.getResponse().isCommitted()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.securechannel;
|
||||
|
||||
import net.sf.acegisecurity.ConfigAttribute;
|
||||
import net.sf.acegisecurity.ConfigAttributeDefinition;
|
||||
import net.sf.acegisecurity.intercept.web.FilterInvocation;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
|
||||
/**
|
||||
* Decides whether a web channel meets a specific security condition.
|
||||
*
|
||||
* <P>
|
||||
* <code>ChannelProcessor</code> implementations are iterated by the {@link
|
||||
* ChannelDecisionManagerImpl}.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* If an implementation has an issue with the channel security, they should
|
||||
* take action themselves. The callers of the implementation do not take any
|
||||
* action.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface ChannelProcessor {
|
||||
//~ Methods ================================================================
|
||||
|
||||
/**
|
||||
* Decided whether the presented {@link FilterInvocation} provides the
|
||||
* appropriate level of channel security based on the requested {@link
|
||||
* ConfigAttributeDefinition}.
|
||||
*/
|
||||
public void decide(FilterInvocation invocation,
|
||||
ConfigAttributeDefinition config) throws IOException, ServletException;
|
||||
|
||||
/**
|
||||
* Indicates whether this <code>ChannelProcessor</code> is able to process
|
||||
* the passed <code>ConfigAttribute</code>.
|
||||
*
|
||||
* <p>
|
||||
* This allows the <code>ChannelProcessingFilter</code> to check every
|
||||
* configuration attribute can be consumed by the configured
|
||||
* <code>ChannelDecisionManager</code>.
|
||||
* </p>
|
||||
*
|
||||
* @param attribute a configuration attribute that has been configured
|
||||
* against the <code>ChannelProcessingFilter</code>
|
||||
*
|
||||
* @return true if this <code>ChannelProcessor</code> can support the
|
||||
* passed configuration attribute
|
||||
*/
|
||||
public boolean supports(ConfigAttribute attribute);
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.securechannel;
|
||||
|
||||
import net.sf.acegisecurity.ConfigAttribute;
|
||||
import net.sf.acegisecurity.ConfigAttributeDefinition;
|
||||
import net.sf.acegisecurity.intercept.web.FilterInvocation;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Ensures channel security is inactive by review of
|
||||
* <code>HttpServletRequest.isSecure()</code> responses.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* The class responds to one case-sensitive keyword, {@link
|
||||
* #getInsecureKeyword}. If this keyword is detected,
|
||||
* <code>HttpServletRequest.isSecure()</code> is used to determine the channel
|
||||
* security offered. If channel security is present, the configured
|
||||
* <code>ChannelEntryPoint</code> is called. By default the entry point is
|
||||
* {@link RetryWithHttpEntryPoint}.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* The default <code>insecureKeyword</code> is
|
||||
* <code>REQUIRES_INSECURE_CHANNEL</code>.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class InsecureChannelProcessor implements InitializingBean,
|
||||
ChannelProcessor {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private ChannelEntryPoint entryPoint = new RetryWithHttpEntryPoint();
|
||||
private String insecureKeyword = "REQUIRES_INSECURE_CHANNEL";
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setEntryPoint(ChannelEntryPoint entryPoint) {
|
||||
this.entryPoint = entryPoint;
|
||||
}
|
||||
|
||||
public ChannelEntryPoint getEntryPoint() {
|
||||
return entryPoint;
|
||||
}
|
||||
|
||||
public void setInsecureKeyword(String secureKeyword) {
|
||||
this.insecureKeyword = secureKeyword;
|
||||
}
|
||||
|
||||
public String getInsecureKeyword() {
|
||||
return insecureKeyword;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if ((insecureKeyword == null) || "".equals(insecureKeyword)) {
|
||||
throw new IllegalArgumentException("insecureKeyword required");
|
||||
}
|
||||
|
||||
if (entryPoint == null) {
|
||||
throw new IllegalArgumentException("entryPoint required");
|
||||
}
|
||||
}
|
||||
|
||||
public void decide(FilterInvocation invocation,
|
||||
ConfigAttributeDefinition config) throws IOException, ServletException {
|
||||
if ((invocation == null) || (config == null)) {
|
||||
throw new IllegalArgumentException("Nulls cannot be provided");
|
||||
}
|
||||
|
||||
Iterator iter = config.getConfigAttributes();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
ConfigAttribute attribute = (ConfigAttribute) iter.next();
|
||||
|
||||
if (supports(attribute)) {
|
||||
if (invocation.getHttpRequest().isSecure()) {
|
||||
entryPoint.commence(invocation.getRequest(),
|
||||
invocation.getResponse());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
if ((attribute != null) && (attribute.getAttribute() != null)
|
||||
&& attribute.getAttribute().equals(getInsecureKeyword())) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.securechannel;
|
||||
|
||||
import net.sf.acegisecurity.AccessDeniedException;
|
||||
|
||||
|
||||
/**
|
||||
* Thrown if a secure web channel is detected, but is not required.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class InsecureChannelRequiredException extends AccessDeniedException {
|
||||
//~ Constructors ===========================================================
|
||||
|
||||
/**
|
||||
* Constructs an <code>InsecureChannelRequiredException</code> with the
|
||||
* specified message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
*/
|
||||
public InsecureChannelRequiredException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an <code>InsecureChannelRequiredException</code> with the
|
||||
* specified message and root cause.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
* @param t root cause
|
||||
*/
|
||||
public InsecureChannelRequiredException(String msg, Throwable t) {
|
||||
super(msg, t);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.securechannel;
|
||||
|
||||
import net.sf.acegisecurity.ConfigAttribute;
|
||||
import net.sf.acegisecurity.ConfigAttributeDefinition;
|
||||
import net.sf.acegisecurity.intercept.web.FilterInvocation;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Ensures channel security is active by review of
|
||||
* <code>HttpServletRequest.isSecure()</code> responses.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* The class responds to one case-sensitive keyword, {@link #getSecureKeyword}.
|
||||
* If this keyword is detected, <code>HttpServletRequest.isSecure()</code> is
|
||||
* used to determine the channel security offered. If channel security is not
|
||||
* present, the configured <code>ChannelEntryPoint</code> is called. By
|
||||
* default the entry point is {@link RetryWithHttpsEntryPoint}.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* The default <code>secureKeyword</code> is
|
||||
* <code>REQUIRES_SECURE_CHANNEL</code>.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SecureChannelProcessor implements InitializingBean,
|
||||
ChannelProcessor {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private ChannelEntryPoint entryPoint = new RetryWithHttpsEntryPoint();
|
||||
private String secureKeyword = "REQUIRES_SECURE_CHANNEL";
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setEntryPoint(ChannelEntryPoint entryPoint) {
|
||||
this.entryPoint = entryPoint;
|
||||
}
|
||||
|
||||
public ChannelEntryPoint getEntryPoint() {
|
||||
return entryPoint;
|
||||
}
|
||||
|
||||
public void setSecureKeyword(String secureKeyword) {
|
||||
this.secureKeyword = secureKeyword;
|
||||
}
|
||||
|
||||
public String getSecureKeyword() {
|
||||
return secureKeyword;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if ((secureKeyword == null) || "".equals(secureKeyword)) {
|
||||
throw new IllegalArgumentException("secureKeyword required");
|
||||
}
|
||||
|
||||
if (entryPoint == null) {
|
||||
throw new IllegalArgumentException("entryPoint required");
|
||||
}
|
||||
}
|
||||
|
||||
public void decide(FilterInvocation invocation,
|
||||
ConfigAttributeDefinition config) throws IOException, ServletException {
|
||||
if ((invocation == null) || (config == null)) {
|
||||
throw new IllegalArgumentException("Nulls cannot be provided");
|
||||
}
|
||||
|
||||
Iterator iter = config.getConfigAttributes();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
ConfigAttribute attribute = (ConfigAttribute) iter.next();
|
||||
|
||||
if (supports(attribute)) {
|
||||
if (!invocation.getHttpRequest().isSecure()) {
|
||||
entryPoint.commence(invocation.getRequest(),
|
||||
invocation.getResponse());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
if ((attribute != null) && (attribute.getAttribute() != null)
|
||||
&& attribute.getAttribute().equals(getSecureKeyword())) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.securechannel;
|
||||
|
||||
import net.sf.acegisecurity.AccessDeniedException;
|
||||
|
||||
|
||||
/**
|
||||
* Thrown if a secure web channel is required, but is not present.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SecureChannelRequiredException extends AccessDeniedException {
|
||||
//~ Constructors ===========================================================
|
||||
|
||||
/**
|
||||
* Constructs a <code>SecureChannelRequiredException</code> with the
|
||||
* specified message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
*/
|
||||
public SecureChannelRequiredException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a <code>SecureChannelRequiredException</code> with the
|
||||
* specified message and root cause.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
* @param t root cause
|
||||
*/
|
||||
public SecureChannelRequiredException(String msg, Throwable t) {
|
||||
super(msg, t);
|
||||
}
|
||||
}
|
||||
@@ -56,7 +56,11 @@ public class MockHttpServletResponse implements HttpServletResponse {
|
||||
}
|
||||
|
||||
public boolean isCommitted() {
|
||||
throw new UnsupportedOperationException("mock method not implemented");
|
||||
if (redirect == null) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void setContentLength(int arg0) {
|
||||
|
||||
+149
-106
@@ -17,6 +17,7 @@ package net.sf.acegisecurity.securechannel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import net.sf.acegisecurity.ConfigAttribute;
|
||||
import net.sf.acegisecurity.ConfigAttributeDefinition;
|
||||
import net.sf.acegisecurity.MockFilterChain;
|
||||
import net.sf.acegisecurity.MockHttpServletRequest;
|
||||
@@ -24,6 +25,14 @@ import net.sf.acegisecurity.MockHttpServletResponse;
|
||||
import net.sf.acegisecurity.SecurityConfig;
|
||||
import net.sf.acegisecurity.intercept.web.FilterInvocation;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link ChannelDecisionManagerImpl}.
|
||||
@@ -42,141 +51,175 @@ public class ChannelDecisionManagerImplTests extends TestCase {
|
||||
junit.textui.TestRunner.run(ChannelDecisionManagerImplTests.class);
|
||||
}
|
||||
|
||||
public void testDetectsInvalidInsecureKeyword() throws Exception {
|
||||
public void testCannotSetEmptyChannelProcessorsList()
|
||||
throws Exception {
|
||||
ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl();
|
||||
cdm.setInsecureKeyword("");
|
||||
|
||||
try {
|
||||
cdm.afterPropertiesSet();
|
||||
cdm.setChannelProcessors(new Vector());
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("insecureKeyword required", expected.getMessage());
|
||||
}
|
||||
|
||||
cdm.setInsecureKeyword(null);
|
||||
|
||||
try {
|
||||
cdm.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("insecureKeyword required", expected.getMessage());
|
||||
assertEquals("A list of ChannelProcessors is required",
|
||||
expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testDetectsInvalidSecureKeyword() throws Exception {
|
||||
public void testCannotSetIncorrectObjectTypesIntoChannelProcessorsList()
|
||||
throws Exception {
|
||||
ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl();
|
||||
cdm.setSecureKeyword("");
|
||||
List list = new Vector();
|
||||
list.add("THIS IS NOT A CHANNELPROCESSOR");
|
||||
|
||||
try {
|
||||
cdm.afterPropertiesSet();
|
||||
cdm.setChannelProcessors(list);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("secureKeyword required", expected.getMessage());
|
||||
}
|
||||
|
||||
cdm.setSecureKeyword(null);
|
||||
|
||||
try {
|
||||
cdm.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("secureKeyword required", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testDetectsNullsPassedToMainMethod() {
|
||||
ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl();
|
||||
|
||||
try {
|
||||
cdm.decide(null, new ConfigAttributeDefinition());
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("Nulls cannot be provided", expected.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
cdm.decide(new FilterInvocation(new MockHttpServletRequest("x"),
|
||||
new MockHttpServletResponse(), new MockFilterChain()), null);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("Nulls cannot be provided", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testDetectsWhenInsecureChannelNeededAndInsecureSchemeUsed() {
|
||||
ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
|
||||
attr.addConfigAttribute(new SecurityConfig(
|
||||
"SOME_CONFIG_ATTRIBUTE_TO_IGNORE"));
|
||||
attr.addConfigAttribute(new SecurityConfig("REQUIRES_INSECURE_CHANNEL"));
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("foo=bar");
|
||||
request.setScheme("http");
|
||||
|
||||
ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl();
|
||||
cdm.decide(new FilterInvocation(request, new MockHttpServletResponse(),
|
||||
new MockFilterChain()), attr);
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
public void testDetectsWhenInsecureChannelNeededAndSecureSchemeUsed() {
|
||||
ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
|
||||
attr.addConfigAttribute(new SecurityConfig(
|
||||
"SOME_CONFIG_ATTRIBUTE_TO_IGNORE"));
|
||||
attr.addConfigAttribute(new SecurityConfig("REQUIRES_INSECURE_CHANNEL"));
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("foo=bar");
|
||||
request.setScheme("https");
|
||||
|
||||
ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl();
|
||||
|
||||
try {
|
||||
cdm.decide(new FilterInvocation(request,
|
||||
new MockHttpServletResponse(), new MockFilterChain()), attr);
|
||||
} catch (InsecureChannelRequiredException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testDetectsWhenSecureChannelNeeded() {
|
||||
ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
|
||||
attr.addConfigAttribute(new SecurityConfig(
|
||||
"SOME_CONFIG_ATTRIBUTE_TO_IGNORE"));
|
||||
attr.addConfigAttribute(new SecurityConfig("REQUIRES_SECURE_CHANNEL"));
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("foo=bar");
|
||||
request.setScheme("http");
|
||||
|
||||
public void testCannotSetNullChannelProcessorsList()
|
||||
throws Exception {
|
||||
ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl();
|
||||
|
||||
try {
|
||||
cdm.decide(new FilterInvocation(request,
|
||||
new MockHttpServletResponse(), new MockFilterChain()), attr);
|
||||
} catch (SecureChannelRequiredException expected) {
|
||||
assertTrue(true);
|
||||
cdm.setChannelProcessors(null);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("A list of ChannelProcessors is required",
|
||||
expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetterSetters() throws Exception {
|
||||
public void testDecideIsOperational() throws Exception {
|
||||
ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl();
|
||||
MockChannelProcessor cpXyz = new MockChannelProcessor("xyz", false);
|
||||
MockChannelProcessor cpAbc = new MockChannelProcessor("abc", true);
|
||||
List list = new Vector();
|
||||
list.add(cpXyz);
|
||||
list.add(cpAbc);
|
||||
cdm.setChannelProcessors(list);
|
||||
cdm.afterPropertiesSet();
|
||||
assertEquals("REQUIRES_INSECURE_CHANNEL", cdm.getInsecureKeyword());
|
||||
assertEquals("REQUIRES_SECURE_CHANNEL", cdm.getSecureKeyword());
|
||||
|
||||
cdm.setInsecureKeyword("MY_INSECURE");
|
||||
cdm.setSecureKeyword("MY_SECURE");
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("not used");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockFilterChain chain = new MockFilterChain();
|
||||
FilterInvocation fi = new FilterInvocation(request, response, chain);
|
||||
|
||||
assertEquals("MY_INSECURE", cdm.getInsecureKeyword());
|
||||
assertEquals("MY_SECURE", cdm.getSecureKeyword());
|
||||
ConfigAttributeDefinition cad = new ConfigAttributeDefinition();
|
||||
cad.addConfigAttribute(new SecurityConfig("xyz"));
|
||||
|
||||
cdm.decide(fi, cad);
|
||||
assertTrue(fi.getResponse().isCommitted());
|
||||
}
|
||||
|
||||
public void testIgnoresOtherConfigAttributes() {
|
||||
ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
|
||||
attr.addConfigAttribute(new SecurityConfig("XYZ"));
|
||||
|
||||
public void testDecideIteratesAllProcessorsIfNoneCommitAResponse()
|
||||
throws Exception {
|
||||
ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl();
|
||||
cdm.decide(new FilterInvocation(new MockHttpServletRequest("x"),
|
||||
new MockHttpServletResponse(), new MockFilterChain()), attr);
|
||||
assertTrue(true);
|
||||
MockChannelProcessor cpXyz = new MockChannelProcessor("xyz", false);
|
||||
MockChannelProcessor cpAbc = new MockChannelProcessor("abc", false);
|
||||
List list = new Vector();
|
||||
list.add(cpXyz);
|
||||
list.add(cpAbc);
|
||||
cdm.setChannelProcessors(list);
|
||||
cdm.afterPropertiesSet();
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("not used");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockFilterChain chain = new MockFilterChain();
|
||||
FilterInvocation fi = new FilterInvocation(request, response, chain);
|
||||
|
||||
ConfigAttributeDefinition cad = new ConfigAttributeDefinition();
|
||||
cad.addConfigAttribute(new SecurityConfig(
|
||||
"SOME_ATTRIBUTE_NO_PROCESSORS_SUPPORT"));
|
||||
|
||||
cdm.decide(fi, cad);
|
||||
assertFalse(fi.getResponse().isCommitted());
|
||||
}
|
||||
|
||||
public void testDelegatesSupports() throws Exception {
|
||||
ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl();
|
||||
MockChannelProcessor cpXyz = new MockChannelProcessor("xyz", false);
|
||||
MockChannelProcessor cpAbc = new MockChannelProcessor("abc", false);
|
||||
List list = new Vector();
|
||||
list.add(cpXyz);
|
||||
list.add(cpAbc);
|
||||
cdm.setChannelProcessors(list);
|
||||
cdm.afterPropertiesSet();
|
||||
|
||||
assertTrue(cdm.supports(new SecurityConfig("xyz")));
|
||||
assertTrue(cdm.supports(new SecurityConfig("abc")));
|
||||
assertFalse(cdm.supports(new SecurityConfig("UNSUPPORTED")));
|
||||
}
|
||||
|
||||
public void testGettersSetters() {
|
||||
ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl();
|
||||
assertNull(cdm.getChannelProcessors());
|
||||
|
||||
MockChannelProcessor cpXyz = new MockChannelProcessor("xyz", false);
|
||||
MockChannelProcessor cpAbc = new MockChannelProcessor("abc", false);
|
||||
List list = new Vector();
|
||||
list.add(cpXyz);
|
||||
list.add(cpAbc);
|
||||
cdm.setChannelProcessors(list);
|
||||
|
||||
assertEquals(list, cdm.getChannelProcessors());
|
||||
}
|
||||
|
||||
public void testStartupFailsWithEmptyChannelProcessorsList()
|
||||
throws Exception {
|
||||
ChannelDecisionManagerImpl cdm = new ChannelDecisionManagerImpl();
|
||||
|
||||
try {
|
||||
cdm.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("A list of ChannelProcessors is required",
|
||||
expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
//~ Inner Classes ==========================================================
|
||||
|
||||
private class MockChannelProcessor implements ChannelProcessor {
|
||||
private String configAttribute;
|
||||
private boolean failIfCalled;
|
||||
|
||||
public MockChannelProcessor(String configAttribute, boolean failIfCalled) {
|
||||
this.configAttribute = configAttribute;
|
||||
this.failIfCalled = failIfCalled;
|
||||
}
|
||||
|
||||
private MockChannelProcessor() {
|
||||
super();
|
||||
}
|
||||
|
||||
public void decide(FilterInvocation invocation,
|
||||
ConfigAttributeDefinition config)
|
||||
throws IOException, ServletException {
|
||||
Iterator iter = config.getConfigAttributes();
|
||||
|
||||
if (failIfCalled) {
|
||||
fail("Should not have called this channel processor");
|
||||
}
|
||||
|
||||
while (iter.hasNext()) {
|
||||
ConfigAttribute attr = (ConfigAttribute) iter.next();
|
||||
|
||||
if (attr.equals(configAttribute)) {
|
||||
invocation.getHttpResponse().sendRedirect("/redirected");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
if (attribute.getAttribute().equals(configAttribute)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
+149
-141
@@ -17,18 +17,19 @@ package net.sf.acegisecurity.securechannel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import net.sf.acegisecurity.ConfigAttribute;
|
||||
import net.sf.acegisecurity.ConfigAttributeDefinition;
|
||||
import net.sf.acegisecurity.MockFilterConfig;
|
||||
import net.sf.acegisecurity.MockHttpServletRequest;
|
||||
import net.sf.acegisecurity.MockHttpServletResponse;
|
||||
import net.sf.acegisecurity.SecurityConfig;
|
||||
import net.sf.acegisecurity.intercept.web.FilterInvocation;
|
||||
import net.sf.acegisecurity.intercept.web.FilterInvocationDefinitionSource;
|
||||
import net.sf.acegisecurity.intercept.web.RegExpBasedFilterInvocationDefinitionMap;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
@@ -53,61 +54,16 @@ public class ChannelProcessingFilterTests extends TestCase {
|
||||
junit.textui.TestRunner.run(ChannelProcessingFilterTests.class);
|
||||
}
|
||||
|
||||
public void testCallsInsecureEntryPointWhenTooMuchChannelSecurity()
|
||||
throws Exception {
|
||||
ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
|
||||
attr.addConfigAttribute(new SecurityConfig("REQUIRES_INSECURE_CHANNEL"));
|
||||
|
||||
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path",
|
||||
attr);
|
||||
|
||||
ChannelProcessingFilter filter = new ChannelProcessingFilter();
|
||||
filter.setInsecureChannelEntryPoint(new MockEntryPoint(true));
|
||||
filter.setSecureChannelEntryPoint(new MockEntryPoint(false));
|
||||
filter.setFilterInvocationDefinitionSource(fids);
|
||||
filter.setChannelDecisionManager(new ChannelDecisionManagerImpl());
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("info=now");
|
||||
request.setServletPath("/path");
|
||||
request.setScheme("https");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockFilterChain chain = new MockFilterChain(false);
|
||||
|
||||
filter.doFilter(request, response, chain);
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
public void testCallsSecureEntryPointWhenTooLittleChannelSecurity()
|
||||
throws Exception {
|
||||
ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
|
||||
attr.addConfigAttribute(new SecurityConfig("REQUIRES_SECURE_CHANNEL"));
|
||||
|
||||
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path",
|
||||
attr);
|
||||
|
||||
ChannelProcessingFilter filter = new ChannelProcessingFilter();
|
||||
filter.setInsecureChannelEntryPoint(new MockEntryPoint(false));
|
||||
filter.setSecureChannelEntryPoint(new MockEntryPoint(true));
|
||||
filter.setFilterInvocationDefinitionSource(fids);
|
||||
filter.setChannelDecisionManager(new ChannelDecisionManagerImpl());
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("info=now");
|
||||
request.setServletPath("/path");
|
||||
request.setScheme("http");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockFilterChain chain = new MockFilterChain(false);
|
||||
|
||||
filter.doFilter(request, response, chain);
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
public void testDetectsMissingChannelDecisionManager()
|
||||
throws Exception {
|
||||
ChannelProcessingFilter filter = new ChannelProcessingFilter();
|
||||
filter.setSecureChannelEntryPoint(new RetryWithHttpsEntryPoint());
|
||||
filter.setFilterInvocationDefinitionSource(new RegExpBasedFilterInvocationDefinitionMap());
|
||||
|
||||
ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
|
||||
attr.addConfigAttribute(new SecurityConfig("MOCK"));
|
||||
|
||||
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path",
|
||||
attr, true);
|
||||
filter.setFilterInvocationDefinitionSource(fids);
|
||||
|
||||
try {
|
||||
filter.afterPropertiesSet();
|
||||
@@ -118,12 +74,11 @@ public class ChannelProcessingFilterTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testDetectsMissingFilterInvocationDefinitionMap()
|
||||
public void testDetectsMissingFilterInvocationDefinitionSource()
|
||||
throws Exception {
|
||||
ChannelProcessingFilter filter = new ChannelProcessingFilter();
|
||||
filter.setInsecureChannelEntryPoint(new RetryWithHttpEntryPoint());
|
||||
filter.setSecureChannelEntryPoint(new RetryWithHttpsEntryPoint());
|
||||
filter.setChannelDecisionManager(new ChannelDecisionManagerImpl());
|
||||
filter.setChannelDecisionManager(new MockChannelDecisionManager(false,
|
||||
"MOCK"));
|
||||
|
||||
try {
|
||||
filter.afterPropertiesSet();
|
||||
@@ -134,36 +89,116 @@ public class ChannelProcessingFilterTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testDetectsMissingInsecureChannelEntryPoint()
|
||||
public void testDetectsSupportedConfigAttribute() throws Exception {
|
||||
ChannelProcessingFilter filter = new ChannelProcessingFilter();
|
||||
filter.setChannelDecisionManager(new MockChannelDecisionManager(false,
|
||||
"SUPPORTS_MOCK_ONLY"));
|
||||
|
||||
ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
|
||||
attr.addConfigAttribute(new SecurityConfig("SUPPORTS_MOCK_ONLY"));
|
||||
|
||||
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path",
|
||||
attr, true);
|
||||
|
||||
filter.setFilterInvocationDefinitionSource(fids);
|
||||
|
||||
filter.afterPropertiesSet();
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
public void testDetectsUnsupportedConfigAttribute()
|
||||
throws Exception {
|
||||
ChannelProcessingFilter filter = new ChannelProcessingFilter();
|
||||
filter.setSecureChannelEntryPoint(new RetryWithHttpsEntryPoint());
|
||||
filter.setFilterInvocationDefinitionSource(new RegExpBasedFilterInvocationDefinitionMap());
|
||||
filter.setChannelDecisionManager(new ChannelDecisionManagerImpl());
|
||||
filter.setChannelDecisionManager(new MockChannelDecisionManager(false,
|
||||
"SUPPORTS_MOCK_ONLY"));
|
||||
|
||||
ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
|
||||
attr.addConfigAttribute(new SecurityConfig("SUPPORTS_MOCK_ONLY"));
|
||||
attr.addConfigAttribute(new SecurityConfig("INVALID_ATTRIBUTE"));
|
||||
|
||||
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path",
|
||||
attr, true);
|
||||
|
||||
filter.setFilterInvocationDefinitionSource(fids);
|
||||
|
||||
try {
|
||||
filter.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("insecureChannelEntryPoint must be specified",
|
||||
expected.getMessage());
|
||||
assertTrue(expected.getMessage().startsWith("Unsupported configuration attributes:"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testDetectsMissingSecureChannelEntryPoint()
|
||||
public void testDoFilterWhenManagerDoesCommitResponse()
|
||||
throws Exception {
|
||||
ChannelProcessingFilter filter = new ChannelProcessingFilter();
|
||||
filter.setInsecureChannelEntryPoint(new RetryWithHttpEntryPoint());
|
||||
filter.setFilterInvocationDefinitionSource(new RegExpBasedFilterInvocationDefinitionMap());
|
||||
filter.setChannelDecisionManager(new ChannelDecisionManagerImpl());
|
||||
filter.setChannelDecisionManager(new MockChannelDecisionManager(true,
|
||||
"SOME_ATTRIBUTE"));
|
||||
|
||||
try {
|
||||
filter.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("secureChannelEntryPoint must be specified",
|
||||
expected.getMessage());
|
||||
}
|
||||
ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
|
||||
attr.addConfigAttribute(new SecurityConfig("SOME_ATTRIBUTE"));
|
||||
|
||||
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path",
|
||||
attr, true);
|
||||
|
||||
filter.setFilterInvocationDefinitionSource(fids);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("info=now");
|
||||
request.setServletPath("/path");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockFilterChain chain = new MockFilterChain(false);
|
||||
|
||||
filter.doFilter(request, response, chain);
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
public void testDoFilterWhenManagerDoesNotCommitResponse()
|
||||
throws Exception {
|
||||
ChannelProcessingFilter filter = new ChannelProcessingFilter();
|
||||
filter.setChannelDecisionManager(new MockChannelDecisionManager(false,
|
||||
"SOME_ATTRIBUTE"));
|
||||
|
||||
ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
|
||||
attr.addConfigAttribute(new SecurityConfig("SOME_ATTRIBUTE"));
|
||||
|
||||
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path",
|
||||
attr, true);
|
||||
|
||||
filter.setFilterInvocationDefinitionSource(fids);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("info=now");
|
||||
request.setServletPath("/path");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockFilterChain chain = new MockFilterChain(true);
|
||||
|
||||
filter.doFilter(request, response, chain);
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
public void testDoFilterWhenNullConfigAttributeReturned()
|
||||
throws Exception {
|
||||
ChannelProcessingFilter filter = new ChannelProcessingFilter();
|
||||
filter.setChannelDecisionManager(new MockChannelDecisionManager(false,
|
||||
"NOT_USED"));
|
||||
|
||||
ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
|
||||
attr.addConfigAttribute(new SecurityConfig("NOT_USED"));
|
||||
|
||||
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path",
|
||||
attr, true);
|
||||
|
||||
filter.setFilterInvocationDefinitionSource(fids);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("info=now");
|
||||
request.setServletPath("/PATH_NOT_MATCHING_CONFIG_ATTRIBUTE");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockFilterChain chain = new MockFilterChain(true);
|
||||
|
||||
filter.doFilter(request, response, chain);
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
public void testDoFilterWithNonHttpServletRequestDetected()
|
||||
@@ -192,91 +227,55 @@ public class ChannelProcessingFilterTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testDoesNotInterruptRequestsWithCorrectChannelSecurity()
|
||||
throws Exception {
|
||||
public void testGetterSetters() throws Exception {
|
||||
ChannelProcessingFilter filter = new ChannelProcessingFilter();
|
||||
filter.setChannelDecisionManager(new MockChannelDecisionManager(false,
|
||||
"MOCK"));
|
||||
assertTrue(filter.getChannelDecisionManager() != null);
|
||||
|
||||
ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
|
||||
attr.addConfigAttribute(new SecurityConfig("REQUIRES_SECURE_CHANNEL"));
|
||||
attr.addConfigAttribute(new SecurityConfig("MOCK"));
|
||||
|
||||
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path",
|
||||
attr);
|
||||
attr, false);
|
||||
|
||||
ChannelProcessingFilter filter = new ChannelProcessingFilter();
|
||||
filter.setInsecureChannelEntryPoint(new RetryWithHttpEntryPoint());
|
||||
filter.setSecureChannelEntryPoint(new RetryWithHttpsEntryPoint());
|
||||
filter.setFilterInvocationDefinitionSource(fids);
|
||||
filter.setChannelDecisionManager(new ChannelDecisionManagerImpl());
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("info=now");
|
||||
request.setServletPath("/path");
|
||||
request.setScheme("https");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockFilterChain chain = new MockFilterChain(true);
|
||||
|
||||
filter.doFilter(request, response, chain);
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
public void testDoesNotInterruptRequestsWithNoConfigAttribute()
|
||||
throws Exception {
|
||||
ChannelProcessingFilter filter = new ChannelProcessingFilter();
|
||||
filter.setInsecureChannelEntryPoint(new RetryWithHttpEntryPoint());
|
||||
filter.setSecureChannelEntryPoint(new RetryWithHttpsEntryPoint());
|
||||
filter.setFilterInvocationDefinitionSource(new RegExpBasedFilterInvocationDefinitionMap());
|
||||
filter.setChannelDecisionManager(new ChannelDecisionManagerImpl());
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("info=now");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockFilterChain chain = new MockFilterChain(true);
|
||||
|
||||
filter.doFilter(request, response, chain);
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
public void testGetterSetters() {
|
||||
ChannelProcessingFilter filter = new ChannelProcessingFilter();
|
||||
filter.setInsecureChannelEntryPoint(new RetryWithHttpEntryPoint());
|
||||
filter.setSecureChannelEntryPoint(new RetryWithHttpsEntryPoint());
|
||||
filter.setFilterInvocationDefinitionSource(new RegExpBasedFilterInvocationDefinitionMap());
|
||||
filter.setChannelDecisionManager(new ChannelDecisionManagerImpl());
|
||||
|
||||
assertTrue(filter.getInsecureChannelEntryPoint() != null);
|
||||
assertTrue(filter.getSecureChannelEntryPoint() != null);
|
||||
assertTrue(filter.getFilterInvocationDefinitionSource() != null);
|
||||
assertTrue(filter.getChannelDecisionManager() != null);
|
||||
}
|
||||
|
||||
public void testLifecycle() throws Exception {
|
||||
ChannelProcessingFilter filter = new ChannelProcessingFilter();
|
||||
filter.setInsecureChannelEntryPoint(new RetryWithHttpEntryPoint());
|
||||
filter.setSecureChannelEntryPoint(new RetryWithHttpsEntryPoint());
|
||||
filter.setFilterInvocationDefinitionSource(new RegExpBasedFilterInvocationDefinitionMap());
|
||||
filter.setChannelDecisionManager(new ChannelDecisionManagerImpl());
|
||||
filter.init(null);
|
||||
filter.afterPropertiesSet();
|
||||
|
||||
filter.init(new MockFilterConfig());
|
||||
filter.destroy();
|
||||
}
|
||||
|
||||
//~ Inner Classes ==========================================================
|
||||
|
||||
private class MockEntryPoint implements ChannelEntryPoint {
|
||||
private boolean expectToBeCalled;
|
||||
private class MockChannelDecisionManager implements ChannelDecisionManager {
|
||||
private String supportAttribute;
|
||||
private boolean commitAResponse;
|
||||
|
||||
public MockEntryPoint(boolean expectToBeCalled) {
|
||||
this.expectToBeCalled = expectToBeCalled;
|
||||
public MockChannelDecisionManager(boolean commitAResponse,
|
||||
String supportAttribute) {
|
||||
this.commitAResponse = commitAResponse;
|
||||
this.supportAttribute = supportAttribute;
|
||||
}
|
||||
|
||||
private MockEntryPoint() {
|
||||
private MockChannelDecisionManager() {
|
||||
super();
|
||||
}
|
||||
|
||||
public void commence(ServletRequest request, ServletResponse response)
|
||||
public void decide(FilterInvocation invocation,
|
||||
ConfigAttributeDefinition config)
|
||||
throws IOException, ServletException {
|
||||
if (expectToBeCalled) {
|
||||
assertTrue(true);
|
||||
if (commitAResponse) {
|
||||
invocation.getHttpResponse().sendRedirect("/redirected");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
if (attribute.getAttribute().equals(supportAttribute)) {
|
||||
return true;
|
||||
} else {
|
||||
fail("Did not expect this ChannelEntryPoint to be called");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -306,11 +305,13 @@ public class ChannelProcessingFilterTests extends TestCase {
|
||||
implements FilterInvocationDefinitionSource {
|
||||
private ConfigAttributeDefinition toReturn;
|
||||
private String servletPath;
|
||||
private boolean provideIterator;
|
||||
|
||||
public MockFilterInvocationDefinitionMap(String servletPath,
|
||||
ConfigAttributeDefinition toReturn) {
|
||||
ConfigAttributeDefinition toReturn, boolean provideIterator) {
|
||||
this.servletPath = servletPath;
|
||||
this.toReturn = toReturn;
|
||||
this.provideIterator = provideIterator;
|
||||
}
|
||||
|
||||
private MockFilterInvocationDefinitionMap() {
|
||||
@@ -329,7 +330,14 @@ public class ChannelProcessingFilterTests extends TestCase {
|
||||
}
|
||||
|
||||
public Iterator getConfigAttributeDefinitions() {
|
||||
return null;
|
||||
if (!provideIterator) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List list = new Vector();
|
||||
list.add(toReturn);
|
||||
|
||||
return list.iterator();
|
||||
}
|
||||
|
||||
public boolean supports(Class clazz) {
|
||||
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.securechannel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import net.sf.acegisecurity.ConfigAttributeDefinition;
|
||||
import net.sf.acegisecurity.MockFilterChain;
|
||||
import net.sf.acegisecurity.MockHttpServletRequest;
|
||||
import net.sf.acegisecurity.MockHttpServletResponse;
|
||||
import net.sf.acegisecurity.SecurityConfig;
|
||||
import net.sf.acegisecurity.intercept.web.FilterInvocation;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link InsecureChannelProcessor}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class InsecureChannelProcessorTests extends TestCase {
|
||||
//~ Methods ================================================================
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(InsecureChannelProcessorTests.class);
|
||||
}
|
||||
|
||||
public void testDecideDetectsAcceptableChannel() throws Exception {
|
||||
ConfigAttributeDefinition cad = new ConfigAttributeDefinition();
|
||||
cad.addConfigAttribute(new SecurityConfig("SOME_IGNORED_ATTRIBUTE"));
|
||||
cad.addConfigAttribute(new SecurityConfig("REQUIRES_INSECURE_CHANNEL"));
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("info=true");
|
||||
request.setServerName("localhost");
|
||||
request.setContextPath("/bigapp");
|
||||
request.setServletPath("/servlet");
|
||||
request.setScheme("http");
|
||||
request.setServerPort(8080);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockFilterChain chain = new MockFilterChain();
|
||||
FilterInvocation fi = new FilterInvocation(request, response, chain);
|
||||
|
||||
InsecureChannelProcessor processor = new InsecureChannelProcessor();
|
||||
processor.decide(fi, cad);
|
||||
|
||||
assertFalse(fi.getResponse().isCommitted());
|
||||
}
|
||||
|
||||
public void testDecideDetectsUnacceptableChannel()
|
||||
throws Exception {
|
||||
ConfigAttributeDefinition cad = new ConfigAttributeDefinition();
|
||||
cad.addConfigAttribute(new SecurityConfig("SOME_IGNORED_ATTRIBUTE"));
|
||||
cad.addConfigAttribute(new SecurityConfig("REQUIRES_INSECURE_CHANNEL"));
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("info=true");
|
||||
request.setServerName("localhost");
|
||||
request.setContextPath("/bigapp");
|
||||
request.setServletPath("/servlet");
|
||||
request.setScheme("https");
|
||||
request.setServerPort(8443);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockFilterChain chain = new MockFilterChain();
|
||||
FilterInvocation fi = new FilterInvocation(request, response, chain);
|
||||
|
||||
InsecureChannelProcessor processor = new InsecureChannelProcessor();
|
||||
processor.decide(fi, cad);
|
||||
|
||||
assertTrue(fi.getResponse().isCommitted());
|
||||
}
|
||||
|
||||
public void testDecideRejectsNulls() throws Exception {
|
||||
InsecureChannelProcessor processor = new InsecureChannelProcessor();
|
||||
processor.afterPropertiesSet();
|
||||
|
||||
try {
|
||||
processor.decide(null, null);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testGettersSetters() {
|
||||
InsecureChannelProcessor processor = new InsecureChannelProcessor();
|
||||
assertEquals("REQUIRES_INSECURE_CHANNEL", processor.getInsecureKeyword());
|
||||
processor.setInsecureKeyword("X");
|
||||
assertEquals("X", processor.getInsecureKeyword());
|
||||
|
||||
assertTrue(processor.getEntryPoint() != null);
|
||||
processor.setEntryPoint(null);
|
||||
assertTrue(processor.getEntryPoint() == null);
|
||||
}
|
||||
|
||||
public void testMissingEntryPoint() throws Exception {
|
||||
InsecureChannelProcessor processor = new InsecureChannelProcessor();
|
||||
processor.setEntryPoint(null);
|
||||
|
||||
try {
|
||||
processor.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("entryPoint required", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testMissingSecureChannelKeyword() throws Exception {
|
||||
InsecureChannelProcessor processor = new InsecureChannelProcessor();
|
||||
processor.setInsecureKeyword(null);
|
||||
|
||||
try {
|
||||
processor.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("insecureKeyword required", expected.getMessage());
|
||||
}
|
||||
|
||||
processor.setInsecureKeyword("");
|
||||
|
||||
try {
|
||||
processor.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("insecureKeyword required", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testSupports() {
|
||||
InsecureChannelProcessor processor = new InsecureChannelProcessor();
|
||||
assertTrue(processor.supports(
|
||||
new SecurityConfig("REQUIRES_INSECURE_CHANNEL")));
|
||||
assertFalse(processor.supports(null));
|
||||
assertFalse(processor.supports(new SecurityConfig("NOT_SUPPORTED")));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.securechannel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import net.sf.acegisecurity.ConfigAttributeDefinition;
|
||||
import net.sf.acegisecurity.MockFilterChain;
|
||||
import net.sf.acegisecurity.MockHttpServletRequest;
|
||||
import net.sf.acegisecurity.MockHttpServletResponse;
|
||||
import net.sf.acegisecurity.SecurityConfig;
|
||||
import net.sf.acegisecurity.intercept.web.FilterInvocation;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link SecureChannelProcessor}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SecureChannelProcessorTests extends TestCase {
|
||||
//~ Methods ================================================================
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(SecureChannelProcessorTests.class);
|
||||
}
|
||||
|
||||
public void testDecideDetectsAcceptableChannel() throws Exception {
|
||||
ConfigAttributeDefinition cad = new ConfigAttributeDefinition();
|
||||
cad.addConfigAttribute(new SecurityConfig("SOME_IGNORED_ATTRIBUTE"));
|
||||
cad.addConfigAttribute(new SecurityConfig("REQUIRES_SECURE_CHANNEL"));
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("info=true");
|
||||
request.setServerName("localhost");
|
||||
request.setContextPath("/bigapp");
|
||||
request.setServletPath("/servlet");
|
||||
request.setScheme("https");
|
||||
request.setServerPort(8443);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockFilterChain chain = new MockFilterChain();
|
||||
FilterInvocation fi = new FilterInvocation(request, response, chain);
|
||||
|
||||
SecureChannelProcessor processor = new SecureChannelProcessor();
|
||||
processor.decide(fi, cad);
|
||||
|
||||
assertFalse(fi.getResponse().isCommitted());
|
||||
}
|
||||
|
||||
public void testDecideDetectsUnacceptableChannel()
|
||||
throws Exception {
|
||||
ConfigAttributeDefinition cad = new ConfigAttributeDefinition();
|
||||
cad.addConfigAttribute(new SecurityConfig("SOME_IGNORED_ATTRIBUTE"));
|
||||
cad.addConfigAttribute(new SecurityConfig("REQUIRES_SECURE_CHANNEL"));
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("info=true");
|
||||
request.setServerName("localhost");
|
||||
request.setContextPath("/bigapp");
|
||||
request.setServletPath("/servlet");
|
||||
request.setScheme("http");
|
||||
request.setServerPort(8080);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockFilterChain chain = new MockFilterChain();
|
||||
FilterInvocation fi = new FilterInvocation(request, response, chain);
|
||||
|
||||
SecureChannelProcessor processor = new SecureChannelProcessor();
|
||||
processor.decide(fi, cad);
|
||||
|
||||
assertTrue(fi.getResponse().isCommitted());
|
||||
}
|
||||
|
||||
public void testDecideRejectsNulls() throws Exception {
|
||||
SecureChannelProcessor processor = new SecureChannelProcessor();
|
||||
processor.afterPropertiesSet();
|
||||
|
||||
try {
|
||||
processor.decide(null, null);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testGettersSetters() {
|
||||
SecureChannelProcessor processor = new SecureChannelProcessor();
|
||||
assertEquals("REQUIRES_SECURE_CHANNEL", processor.getSecureKeyword());
|
||||
processor.setSecureKeyword("X");
|
||||
assertEquals("X", processor.getSecureKeyword());
|
||||
|
||||
assertTrue(processor.getEntryPoint() != null);
|
||||
processor.setEntryPoint(null);
|
||||
assertTrue(processor.getEntryPoint() == null);
|
||||
}
|
||||
|
||||
public void testMissingEntryPoint() throws Exception {
|
||||
SecureChannelProcessor processor = new SecureChannelProcessor();
|
||||
processor.setEntryPoint(null);
|
||||
|
||||
try {
|
||||
processor.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("entryPoint required", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testMissingSecureChannelKeyword() throws Exception {
|
||||
SecureChannelProcessor processor = new SecureChannelProcessor();
|
||||
processor.setSecureKeyword(null);
|
||||
|
||||
try {
|
||||
processor.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("secureKeyword required", expected.getMessage());
|
||||
}
|
||||
|
||||
processor.setSecureKeyword("");
|
||||
|
||||
try {
|
||||
processor.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("secureKeyword required", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testSupports() {
|
||||
SecureChannelProcessor processor = new SecureChannelProcessor();
|
||||
assertTrue(processor.supports(
|
||||
new SecurityConfig("REQUIRES_SECURE_CHANNEL")));
|
||||
assertFalse(processor.supports(null));
|
||||
assertFalse(processor.supports(new SecurityConfig("NOT_SUPPORTED")));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user