interceptor for securing endpoints based on new endpoint interception model
namespace support to follow
This commit is contained in:
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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.integration.security;
|
||||
|
||||
import org.springframework.integration.handler.InterceptingMessageHandler;
|
||||
import org.springframework.integration.handler.MessageHandler;
|
||||
import org.springframework.integration.message.Message;
|
||||
import org.springframework.security.context.SecurityContext;
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
|
||||
/**
|
||||
* Associates the {@link SecurityContext} propagated in the message header with
|
||||
* the thread executing the handle call to a {@link MessageHandler}.
|
||||
*
|
||||
* @author Jonas Partner
|
||||
*/
|
||||
public class SecurityContextAssociatingHandlerInterceptor extends InterceptingMessageHandler {
|
||||
|
||||
/**
|
||||
* One time only set the strategy to be stack based to allow use of direct
|
||||
* channels where push and pop is required rather than set and clear
|
||||
*/
|
||||
static {
|
||||
SecurityContextHolder.setStrategyName(StackBasedSecurityContextHolderStrategy.class.getName());
|
||||
}
|
||||
|
||||
public SecurityContextAssociatingHandlerInterceptor(MessageHandler target) {
|
||||
super(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message<?> handle(Message<?> message, MessageHandler target) {
|
||||
if (message.getHeader().getAttributeNames().contains(SecurityContextUtils.SECURITY_CONTEXT_HEADER_ATTRIBUTE)) {
|
||||
return handleInSecurityContext(message, target);
|
||||
}
|
||||
return target.handle(message);
|
||||
}
|
||||
|
||||
private Message<?> handleInSecurityContext(Message<?> message, MessageHandler target) {
|
||||
SecurityContext context = SecurityContextUtils.getSecurityContextFromHeader(message);
|
||||
SecurityContextHolder.setContext(context);
|
||||
try {
|
||||
return target.handle(message);
|
||||
}
|
||||
finally {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.security.config;
|
||||
package org.springframework.integration.security.channel.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -61,7 +61,6 @@ public class SecuredChannelsParser extends AbstractSingleBeanDefinitionParser {
|
||||
String receiveAccess = element.getAttribute("receive-access");
|
||||
String sendAccess = element.getAttribute("send-access");
|
||||
String accessDecisionManager = element.getAttribute("access-decision-manager");
|
||||
String propagation = element.getAttribute("propagate");
|
||||
|
||||
BeanDefinition interceptorBeanDefinition = createSecurityEnforcingChannelInterceptor(accessDecisionManager,
|
||||
sendAccess, receiveAccess);
|
||||
@@ -75,7 +74,6 @@ public class SecuredChannelsParser extends AbstractSingleBeanDefinitionParser {
|
||||
builder.getBeanDefinition().getConstructorArgumentValues()
|
||||
.addGenericArgumentValue(new ValueHolder(patternList));
|
||||
|
||||
setPropagation(Boolean.parseBoolean(propagation), patternList, parserContext);
|
||||
}
|
||||
|
||||
protected List<String> processPatterns(NodeList patternList) {
|
||||
@@ -85,19 +83,6 @@ public class SecuredChannelsParser extends AbstractSingleBeanDefinitionParser {
|
||||
patterns.add(patternElement.getTextContent());
|
||||
}
|
||||
return patterns;
|
||||
|
||||
}
|
||||
|
||||
protected void setPropagation(boolean propagation, List<String> patterns, ParserContext parserContext) {
|
||||
for (String pattern : patterns) {
|
||||
if (propagation) {
|
||||
SecurityPropagatingBeanPostProcessorDefinitionHelper.addToIncludeChannelList(pattern, parserContext);
|
||||
}
|
||||
else {
|
||||
SecurityPropagatingBeanPostProcessorDefinitionHelper.addToExcludeChannelList(pattern, parserContext);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected BeanDefinition createSecurityEnforcingChannelInterceptor(String accessDecisionManager, String sendAccess,
|
||||
@@ -14,11 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.security.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
package org.springframework.integration.security.channel.config;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -27,6 +23,7 @@ import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.integration.channel.AbstractMessageChannel;
|
||||
import org.springframework.integration.security.channel.SecurityContextPropagatingChannelInterceptor;
|
||||
import org.springframework.integration.security.config.OrderedIncludeExcludeList;
|
||||
|
||||
/**
|
||||
* Post processes channels applying appropriate propagation behaviour. If
|
||||
@@ -43,36 +40,12 @@ public class SecurityPropagatingBeanPostProcessor implements BeanPostProcessor,
|
||||
|
||||
private final SecurityContextPropagatingChannelInterceptor interceptor = new SecurityContextPropagatingChannelInterceptor();
|
||||
|
||||
private boolean propagateByDefault;
|
||||
|
||||
private final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
private List<Pattern> channelsToInclude = new ArrayList<Pattern>();
|
||||
private final OrderedIncludeExcludeList includeExcludeList;
|
||||
|
||||
private List<Pattern> channelsToExclude = new ArrayList<Pattern>();
|
||||
|
||||
public boolean isPropagateByDefault() {
|
||||
return this.propagateByDefault;
|
||||
}
|
||||
|
||||
public void setPropagateByDefault(boolean propagateByDefault) {
|
||||
this.propagateByDefault = propagateByDefault;
|
||||
}
|
||||
|
||||
public List<Pattern> getChannelsToInclude() {
|
||||
return this.channelsToInclude;
|
||||
}
|
||||
|
||||
public void setChannelsToInclude(List<Pattern> channelsToInclude) {
|
||||
this.channelsToInclude = channelsToInclude;
|
||||
}
|
||||
|
||||
public List<Pattern> getChannelsToExclude() {
|
||||
return this.channelsToExclude;
|
||||
}
|
||||
|
||||
public void setChannelsToExclude(List<Pattern> channelsToExclude) {
|
||||
this.channelsToExclude = channelsToExclude;
|
||||
public SecurityPropagatingBeanPostProcessor(OrderedIncludeExcludeList includeExcludeList) {
|
||||
this.includeExcludeList = includeExcludeList;
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
@@ -86,7 +59,7 @@ public class SecurityPropagatingBeanPostProcessor implements BeanPostProcessor,
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (AbstractMessageChannel.class.isAssignableFrom(bean.getClass())) {
|
||||
AbstractMessageChannel channel = (AbstractMessageChannel) bean;
|
||||
if (isIncluded(beanName) || (this.propagateByDefault && !isExcluded(beanName))) {
|
||||
if (includeExcludeList.isIncluded(beanName)) {
|
||||
channel.addInterceptor(this.interceptor);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Channel '" + beanName + "' will propagate a SecurityContext.");
|
||||
@@ -99,21 +72,4 @@ public class SecurityPropagatingBeanPostProcessor implements BeanPostProcessor,
|
||||
return bean;
|
||||
}
|
||||
|
||||
protected boolean isExcluded(String str) {
|
||||
return matchesOnePattern(channelsToExclude, str);
|
||||
}
|
||||
|
||||
protected boolean isIncluded(String str) {
|
||||
return matchesOnePattern(channelsToInclude, str);
|
||||
}
|
||||
|
||||
protected boolean matchesOnePattern(List<Pattern> patterns, String str) {
|
||||
for (Pattern pattern : patterns) {
|
||||
if (pattern.matcher(str).matches()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,15 +14,23 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.security.config;
|
||||
package org.springframework.integration.security.channel.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.security.config.IncludeExcludePattern;
|
||||
import org.springframework.integration.security.config.IncludeExcludePatternParser;
|
||||
import org.springframework.integration.security.config.OrderedIncludeExcludeList;
|
||||
import org.springframework.security.context.SecurityContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -34,17 +42,17 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class SecurityPropagatingChannelsParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
IncludeExcludePatternParser includeExcludePatternParser = new IncludeExcludePatternParser();
|
||||
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||
builder.getBeanDefinition().setAbstract(true);
|
||||
String propagation = element.getAttribute("propagate");
|
||||
boolean propagateByDefault = true;
|
||||
if (StringUtils.hasText(propagation)) {
|
||||
propagateByDefault = Boolean.parseBoolean(propagation);
|
||||
}
|
||||
if (propagateByDefault) {
|
||||
SecurityPropagatingBeanPostProcessorDefinitionHelper.setPropagationDefault(true, parserContext);
|
||||
}
|
||||
boolean propagateByDefault = Boolean.parseBoolean(element.getAttribute("propagate-by-default"));
|
||||
OrderedIncludeExcludeList includeExcludeList = includeExcludePatternParser.createFromNodeList(
|
||||
propagateByDefault, element.getChildNodes());
|
||||
builder.getBeanDefinition().setBeanClass(SecurityPropagatingBeanPostProcessor.class);
|
||||
builder.getBeanDefinition().getConstructorArgumentValues().addGenericArgumentValue(
|
||||
new ValueHolder(includeExcludeList));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1,14 +1,30 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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.integration.security.config;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jonas Partner
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class IncludeExcludePattern {
|
||||
|
||||
|
||||
private final boolean isIncludePattern;
|
||||
|
||||
|
||||
private final String pattern;
|
||||
|
||||
public IncludeExcludePattern(boolean isIncludePattern, String pattern) {
|
||||
@@ -17,9 +33,9 @@ public class IncludeExcludePattern {
|
||||
}
|
||||
|
||||
public IncludeExcludePattern(String pattern) {
|
||||
this(true,pattern);
|
||||
this(true, pattern);
|
||||
}
|
||||
|
||||
|
||||
public boolean isIncludePattern() {
|
||||
return isIncludePattern;
|
||||
}
|
||||
@@ -27,5 +43,5 @@ public class IncludeExcludePattern {
|
||||
public String getPattern() {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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.integration.security.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
public class IncludeExcludePatternParser {
|
||||
|
||||
public OrderedIncludeExcludeList createFromNodeList(boolean includeByDefault, NodeList nodeList) {
|
||||
List<IncludeExcludePattern> patterns = new ArrayList<IncludeExcludePattern>();
|
||||
for (int i = 0; i < nodeList.getLength(); i++) {
|
||||
if (nodeList.item(i).getNodeName().equals("includePattern")) {
|
||||
patterns.add(new IncludeExcludePattern(true, ((Element) nodeList.item(i)).getTextContent()));
|
||||
}
|
||||
else if (nodeList.item(i).getNodeName().equals("excludePattern")) {
|
||||
patterns.add(new IncludeExcludePattern(false, ((Element) nodeList.item(i)).getTextContent()));
|
||||
}
|
||||
}
|
||||
return new JdkRegExpOrderedIncludeExcludeList(includeByDefault, patterns);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,6 +17,8 @@
|
||||
package org.springframework.integration.security.config;
|
||||
|
||||
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
import org.springframework.integration.security.channel.config.SecuredChannelsParser;
|
||||
import org.springframework.integration.security.channel.config.SecurityPropagatingChannelsParser;
|
||||
|
||||
/**
|
||||
* Namespace handler for the security namespace.
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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.integration.security.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -6,38 +22,38 @@ import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class JdkRegExpOrderedIncludeExcludeList implements OrderedIncludeExcludeList {
|
||||
|
||||
|
||||
private final boolean includeByDefault;
|
||||
|
||||
|
||||
private final List<PatternHolder> patternHolders;
|
||||
|
||||
public JdkRegExpOrderedIncludeExcludeList(List<IncludeExcludePattern> patterns){
|
||||
|
||||
public JdkRegExpOrderedIncludeExcludeList(List<IncludeExcludePattern> patterns) {
|
||||
this(true, patterns);
|
||||
}
|
||||
|
||||
|
||||
public JdkRegExpOrderedIncludeExcludeList(boolean includeByDefault, List<IncludeExcludePattern> patterns) {
|
||||
super();
|
||||
this.includeByDefault = includeByDefault;
|
||||
List<PatternHolder> patternHolders = new ArrayList<PatternHolder>();
|
||||
for(int i = 0 ; i <patterns.size(); i++){
|
||||
patternHolders.add(new PatternHolder(Pattern.compile(patterns.get(i).getPattern()), patterns.get(i)) );
|
||||
for (int i = 0; i < patterns.size(); i++) {
|
||||
patternHolders.add(new PatternHolder(Pattern.compile(patterns.get(i).getPattern()), patterns.get(i)));
|
||||
}
|
||||
this.patternHolders = Collections.unmodifiableList(patternHolders);
|
||||
}
|
||||
|
||||
public boolean isIncluded(String name) {
|
||||
for(int i = 0; i < patternHolders.size(); i++){
|
||||
if(patternHolders.get(i).compiledPattern.matcher(name).matches()){
|
||||
for (int i = 0; i < patternHolders.size(); i++) {
|
||||
if (patternHolders.get(i).compiledPattern.matcher(name).matches()) {
|
||||
return (patternHolders.get(i).includeExcludePattern.isIncludePattern());
|
||||
}
|
||||
}
|
||||
return includeByDefault;
|
||||
}
|
||||
|
||||
private static class PatternHolder{
|
||||
|
||||
|
||||
private static class PatternHolder {
|
||||
|
||||
private final Pattern compiledPattern;
|
||||
|
||||
|
||||
private final IncludeExcludePattern includeExcludePattern;
|
||||
|
||||
public PatternHolder(Pattern compiledPattern, IncludeExcludePattern includeExcludePattern) {
|
||||
@@ -46,11 +62,6 @@ public class JdkRegExpOrderedIncludeExcludeList implements OrderedIncludeExclude
|
||||
this.includeExcludePattern = includeExcludePattern;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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.integration.security.config;
|
||||
|
||||
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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.integration.security.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanNameReference;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
/**
|
||||
* Helper to configure the per {@link ApplicationContext}
|
||||
* {@link SecurityPropagatingBeanPostProcessor} which determines
|
||||
* {@link SecurityContext} propagation.
|
||||
*
|
||||
* @author Jonas Partner
|
||||
*/
|
||||
public class SecurityPropagatingBeanPostProcessorDefinitionHelper {
|
||||
|
||||
private static final String CHANNELS_TO_INCLUDE = "channelsToInclude";
|
||||
|
||||
private static final String CHANNELS_TO_EXCLUDE = "channelsToExclude";
|
||||
|
||||
private static final String PROPAGATE_BY_DEFAULT = "propagateByDefault";
|
||||
|
||||
public static void setPropagationDefault(boolean valueForPropagationDefault, ParserContext context) {
|
||||
BeanDefinition beanDefintion = getOrCreateSecurityPropagatingBeanPostProcessor(context);
|
||||
beanDefintion.getPropertyValues().addPropertyValue(PROPAGATE_BY_DEFAULT,
|
||||
Boolean.valueOf(valueForPropagationDefault));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void addToExcludeChannelList(String channelName, ParserContext context) {
|
||||
BeanDefinition beanDefintion = getOrCreateSecurityPropagatingBeanPostProcessor(context);
|
||||
List channelsToExclude;
|
||||
if (beanDefintion.getPropertyValues().contains(CHANNELS_TO_EXCLUDE)) {
|
||||
channelsToExclude = (List) beanDefintion.getPropertyValues().getPropertyValue(CHANNELS_TO_EXCLUDE)
|
||||
.getValue();
|
||||
}
|
||||
else {
|
||||
channelsToExclude = new ArrayList<RuntimeBeanNameReference>();
|
||||
beanDefintion.getPropertyValues().addPropertyValue(CHANNELS_TO_EXCLUDE, channelsToExclude);
|
||||
}
|
||||
channelsToExclude.add(channelName);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void addToIncludeChannelList(String channelName, ParserContext context) {
|
||||
BeanDefinition beanDefintion = getOrCreateSecurityPropagatingBeanPostProcessor(context);
|
||||
List channelsToExclude;
|
||||
if (beanDefintion.getPropertyValues().contains(CHANNELS_TO_INCLUDE)) {
|
||||
channelsToExclude = (List) beanDefintion.getPropertyValues().getPropertyValue(CHANNELS_TO_INCLUDE)
|
||||
.getValue();
|
||||
}
|
||||
else {
|
||||
channelsToExclude = new ArrayList<RuntimeBeanNameReference>();
|
||||
beanDefintion.getPropertyValues().addPropertyValue(CHANNELS_TO_INCLUDE, channelsToExclude);
|
||||
}
|
||||
channelsToExclude.add(channelName);
|
||||
}
|
||||
|
||||
private static BeanDefinition getOrCreateSecurityPropagatingBeanPostProcessor(ParserContext context) {
|
||||
BeanDefinition beanDefinition = null;
|
||||
String postProcessorBeanName = SecurityPropagatingBeanPostProcessor.SECURITY_PROPAGATING_BEAN_POST_PROCESSOR_NAME;
|
||||
if (context.getRegistry().containsBeanDefinition(postProcessorBeanName)) {
|
||||
beanDefinition = context.getRegistry().getBeanDefinition(postProcessorBeanName);
|
||||
}
|
||||
if (beanDefinition == null) {
|
||||
beanDefinition = new RootBeanDefinition(SecurityPropagatingBeanPostProcessor.class);
|
||||
context.registerBeanComponent(new BeanComponentDefinition(beanDefinition, postProcessorBeanName));
|
||||
}
|
||||
return beanDefinition;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,7 +24,6 @@
|
||||
<xsd:attribute name="receive-access" type="xsd:string" />
|
||||
<xsd:attribute name="send-access" type="xsd:string" />
|
||||
<xsd:attribute name="access-decision-manager" type="xsd:string" default="accessDecisionManager"/>
|
||||
<xsd:attribute name="propagate" type="xsd:boolean" default="true" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
@@ -49,14 +48,26 @@
|
||||
|
||||
<xsd:element name="security-propagating-channels">
|
||||
<xsd:complexType>
|
||||
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines a bean post processor which propagates the
|
||||
security context.
|
||||
security context by registering interceptors with channels.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="propagate" type="xsd:boolean" default="true" />
|
||||
<xsd:sequence>
|
||||
<xsd:element name="propagation-patterns" type="propagationPatternType" maxOccurs="1" minOccurs="0"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="propagate-by-default" type="xsd:boolean" default="true" />
|
||||
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:complexType name="propagationPatternType">
|
||||
<xsd:choice maxOccurs="unbounded" minOccurs="0">
|
||||
<xsd:element name="includePattern" type="xsd:string"/>
|
||||
<xsd:element name="excludePattern" type="xsd:string"/>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
|
||||
</xsd:schema>
|
||||
@@ -14,9 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.security.target;
|
||||
package org.springframework.integration.security.endpoint;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.integration.message.Message;
|
||||
import org.springframework.integration.security.SecurityContextUtils;
|
||||
@@ -24,33 +23,35 @@ import org.springframework.security.AccessDecisionManager;
|
||||
import org.springframework.security.ConfigAttributeDefinition;
|
||||
import org.springframework.security.context.SecurityContext;
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
import org.springframework.temp.endpoint.EndpointInterceptor;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jonas Partner
|
||||
*
|
||||
*/
|
||||
public class TargetSecuringInterceptor implements MethodInterceptor {
|
||||
public class SecurityEndpointInterceptor implements EndpointInterceptor {
|
||||
|
||||
private final ConfigAttributeDefinition targetSecurityAttributes;
|
||||
|
||||
private final AccessDecisionManager accessDecisionManager;
|
||||
|
||||
public TargetSecuringInterceptor(ConfigAttributeDefinition targetSecurityAttributes,
|
||||
public SecurityEndpointInterceptor(ConfigAttributeDefinition endpointSecurityAttributes,
|
||||
AccessDecisionManager accessDecisionManager) {
|
||||
this.targetSecurityAttributes = targetSecurityAttributes;
|
||||
super();
|
||||
this.targetSecurityAttributes = endpointSecurityAttributes;
|
||||
this.accessDecisionManager = accessDecisionManager;
|
||||
}
|
||||
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
public void aroundInvoke(MethodInvocation invocation) throws Throwable {
|
||||
Message<?> message = (Message<?>) invocation.getArguments()[0];
|
||||
SecurityContext ctx = SecurityContextUtils.getSecurityContextFromHeader(message);
|
||||
if (ctx != null) {
|
||||
|
||||
SecurityContext securityCtx = null;
|
||||
|
||||
if(message != null){
|
||||
securityCtx = SecurityContextUtils.getSecurityContextFromHeader(message);
|
||||
}
|
||||
if (securityCtx != null) {
|
||||
try {
|
||||
SecurityContextHolder.setContext(ctx);
|
||||
SecurityContextHolder.setContext(securityCtx);
|
||||
accessDecisionManager.decide(SecurityContextHolder.getContext().getAuthentication(), invocation
|
||||
.getThis(), targetSecurityAttributes);
|
||||
return invocation.proceed();
|
||||
invocation.proceed();
|
||||
}
|
||||
finally {
|
||||
SecurityContextHolder.clearContext();
|
||||
@@ -59,8 +60,16 @@ public class TargetSecuringInterceptor implements MethodInterceptor {
|
||||
else {
|
||||
accessDecisionManager.decide(SecurityContextHolder.getContext().getAuthentication(), invocation.getThis(),
|
||||
targetSecurityAttributes);
|
||||
return invocation.proceed();
|
||||
invocation.proceed();
|
||||
}
|
||||
}
|
||||
|
||||
public void postInvoke(Message message) {
|
||||
|
||||
}
|
||||
|
||||
public void preInvoke(Message message) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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.integration.security.target;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
import org.springframework.aop.ClassFilter;
|
||||
import org.springframework.aop.MethodMatcher;
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.support.AbstractPointcutAdvisor;
|
||||
import org.springframework.aop.support.ClassFilters;
|
||||
import org.springframework.aop.support.MethodMatchers;
|
||||
import org.springframework.aop.support.NameMatchMethodPointcut;
|
||||
import org.springframework.aop.support.RootClassFilter;
|
||||
import org.springframework.integration.message.BlockingTarget;
|
||||
import org.springframework.integration.message.Target;
|
||||
import org.springframework.security.AccessDecisionManager;
|
||||
import org.springframework.security.ConfigAttributeDefinition;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class TargetSecuringAdvisor extends AbstractPointcutAdvisor implements Pointcut {
|
||||
|
||||
private ClassFilter classFilter;
|
||||
|
||||
private MethodMatcher matcher;
|
||||
|
||||
private Advice targetSecuringInterceptor;
|
||||
|
||||
public TargetSecuringAdvisor(AccessDecisionManager accessDecisionManager, String securityConfig) {
|
||||
targetSecuringInterceptor = new TargetSecuringInterceptor(new ConfigAttributeDefinition(StringUtils
|
||||
.tokenizeToStringArray(securityConfig, ",")), accessDecisionManager);
|
||||
classFilter = ClassFilters.union(new RootClassFilter(Target.class), new RootClassFilter(BlockingTarget.class));
|
||||
NameMatchMethodPointcut nameMatcher = new NameMatchMethodPointcut();
|
||||
nameMatcher.addMethodName("send");
|
||||
matcher = MethodMatchers.intersection(nameMatcher, new TargetSendMethodArgMatcher());
|
||||
}
|
||||
|
||||
public Pointcut getPointcut() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Advice getAdvice() {
|
||||
return targetSecuringInterceptor;
|
||||
}
|
||||
|
||||
public ClassFilter getClassFilter() {
|
||||
return classFilter;
|
||||
}
|
||||
|
||||
public MethodMatcher getMethodMatcher() {
|
||||
return matcher;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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.integration.security.target;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.aop.support.StaticMethodMatcher;
|
||||
import org.springframework.integration.message.Message;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jonas Partner
|
||||
*
|
||||
*/
|
||||
public class TargetSendMethodArgMatcher extends StaticMethodMatcher{
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean matches(Method method, Class targetClass) {
|
||||
return argsTypesMatch(method.getParameterTypes());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected boolean argsTypesMatch(Class[] args){
|
||||
if(args.length > 2){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(args.length > 0){
|
||||
if(!Message.class.isAssignableFrom(args[0] )){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (args.length > 1 ){
|
||||
if(!long.class.isAssignableFrom(args[1])){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package org.springframework.integration.security.target.config;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
public class SecuredTargetsParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
public SecuredTargetsParser() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldGenerateId() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldGenerateIdAsFallback() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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.temp.endpoint;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.integration.message.Message;
|
||||
|
||||
public interface EndpointInterceptor {
|
||||
|
||||
void preInvoke(Message message);
|
||||
|
||||
void aroundInvoke(MethodInvocation invocation) throws Throwable;
|
||||
|
||||
void postInvoke(Message message);
|
||||
}
|
||||
@@ -33,7 +33,7 @@ import org.springframework.integration.message.selector.MessageSelector;
|
||||
/**
|
||||
*
|
||||
* @author Jonas Partner
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ChannelInterceptorRegisteringBeanPostProcessorTests {
|
||||
|
||||
|
||||
@@ -1,171 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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.integration.security;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.integration.handler.MessageHandler;
|
||||
import org.springframework.integration.message.Message;
|
||||
import org.springframework.integration.message.StringMessage;
|
||||
import org.springframework.security.AccessDeniedException;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.GrantedAuthority;
|
||||
import org.springframework.security.context.SecurityContext;
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
|
||||
/**
|
||||
* @author Jonas Partner
|
||||
*/
|
||||
public class SecurityContextAssociatingHandlerInterceptorTests {
|
||||
|
||||
@After
|
||||
public void clearSecurityContext(){
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessageWithSecurityContext() {
|
||||
final StubSecurityContext securityContext = new StubSecurityContext();
|
||||
StringMessage message = new StringMessage("test");
|
||||
SecurityContextUtils.setSecurityContextHeader(securityContext, message);
|
||||
MessageHandler handler = new MessageHandler() {
|
||||
public Message<?> handle(Message<?> message) {
|
||||
SecurityContext associatedContext = SecurityContextHolder.getContext();
|
||||
assertEquals("Wrong security context", securityContext, associatedContext);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
SecurityContextAssociatingHandlerInterceptor associatingInterceptor =
|
||||
new SecurityContextAssociatingHandlerInterceptor(handler);
|
||||
associatingInterceptor.handle(message);
|
||||
assertNull("Security context still present after handler returned",
|
||||
SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
@Test(expected = AccessDeniedException.class)
|
||||
public void testForSecurityLeakageIfHandlerThrowsException() {
|
||||
final StubSecurityContext securityContext = new StubSecurityContext();
|
||||
StringMessage message = new StringMessage("test");
|
||||
SecurityContextUtils.setSecurityContextHeader(securityContext, message);
|
||||
MessageHandler handler = new MessageHandler() {
|
||||
public Message<?> handle(Message<?> message) {
|
||||
SecurityContext associatedContext = SecurityContextHolder.getContext();
|
||||
assertEquals("Wrong security context", securityContext, associatedContext);
|
||||
throw new AccessDeniedException("Not allowed");
|
||||
}
|
||||
};
|
||||
SecurityContextAssociatingHandlerInterceptor associatingInterceptor =
|
||||
new SecurityContextAssociatingHandlerInterceptor(handler);
|
||||
try {
|
||||
associatingInterceptor.handle(message);
|
||||
}
|
||||
finally {
|
||||
assertNull("Security context still present after handler threw exception",
|
||||
SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessageWithoutSecurityContext() {
|
||||
final StubSecurityContext securityContext = new StubSecurityContext();
|
||||
StringMessage message = new StringMessage("test");
|
||||
MessageHandler handler = new MessageHandler() {
|
||||
public Message<?> handle(Message<?> message) {
|
||||
SecurityContext associatedContext = SecurityContextHolder.getContext();
|
||||
assertNotSame("Wrong security context", securityContext, associatedContext);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
SecurityContextAssociatingHandlerInterceptor associatingInterceptor =
|
||||
new SecurityContextAssociatingHandlerInterceptor(handler);
|
||||
associatingInterceptor.handle(message);
|
||||
assertNull("Security context still present after handler returned",
|
||||
SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExistingSecurityContextIsNotCleared(){
|
||||
SecurityContextHolder.setStrategyName(StackBasedSecurityContextHolderStrategy.class.getName());
|
||||
final StubSecurityContext securityContext = new StubSecurityContext();
|
||||
SecurityContextHolder.setContext(securityContext);
|
||||
|
||||
StringMessage message = new StringMessage("test");
|
||||
|
||||
final MessageHandler handler = new MessageHandler() {
|
||||
public Message<?> handle(Message<?> message) {
|
||||
SecurityContext associatedContext = SecurityContextHolder.getContext();
|
||||
assertEquals("Wrong security context", securityContext, associatedContext);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
SecurityContextAssociatingHandlerInterceptor associatingInterceptor =
|
||||
new SecurityContextAssociatingHandlerInterceptor(handler);
|
||||
associatingInterceptor.handle(message);
|
||||
assertEquals("Security context no logner set", securityContext, SecurityContextHolder.getContext());
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class StubSecurityContext implements SecurityContext {
|
||||
|
||||
StubAuthentication stubAuthentication = new StubAuthentication();
|
||||
|
||||
public Authentication getAuthentication() {
|
||||
return stubAuthentication;
|
||||
}
|
||||
|
||||
public void setAuthentication(Authentication authentication) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class StubAuthentication implements Authentication {
|
||||
|
||||
public GrantedAuthority[] getAuthorities() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object getCredentials() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object getDetails() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object getPrincipal() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isAuthenticated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,9 +16,7 @@
|
||||
|
||||
package org.springframework.integration.security.channel;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -36,13 +34,12 @@ import org.springframework.security.context.SecurityContextHolder;
|
||||
* @author Jonas Partner
|
||||
*/
|
||||
public class SecurityContextPropagatingChannelInterceptorTests {
|
||||
|
||||
|
||||
private QueueChannel channel;
|
||||
|
||||
private SecurityContextPropagatingChannelInterceptor securityPropogatingChannelInterceptor;
|
||||
|
||||
private StubSecurityContext securityContext;
|
||||
|
||||
private StubSecurityContext securityContext;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -53,11 +50,10 @@ public class SecurityContextPropagatingChannelInterceptorTests {
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown(){
|
||||
public void tearDown() {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testPropogationWhenSecurityContextExists() {
|
||||
this.associateContextWithThread();
|
||||
@@ -65,11 +61,11 @@ public class SecurityContextPropagatingChannelInterceptorTests {
|
||||
this.channel.send(message);
|
||||
message = (StringMessage) channel.receive(0);
|
||||
MessageHeader header = message.getHeader();
|
||||
assertTrue("No security context attribute found in header.",
|
||||
header.getAttributeNames().contains(SecurityContextUtils.SECURITY_CONTEXT_HEADER_ATTRIBUTE));
|
||||
assertTrue("No security context attribute found in header.", header.getAttributeNames().contains(
|
||||
SecurityContextUtils.SECURITY_CONTEXT_HEADER_ATTRIBUTE));
|
||||
SecurityContext contextFromHeader = SecurityContextUtils.getSecurityContextFromHeader(message);
|
||||
assertEquals("Incorrect security context in message header.", securityContext, contextFromHeader);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeaderNotSetWhenNoSecurityContextExists() {
|
||||
@@ -77,19 +73,16 @@ public class SecurityContextPropagatingChannelInterceptorTests {
|
||||
channel.send(message);
|
||||
message = (StringMessage) channel.receive(0);
|
||||
MessageHeader header = message.getHeader();
|
||||
assertFalse("Security context header found when no security context existed.",
|
||||
header.getAttributeNames().contains(SecurityContextUtils.SECURITY_CONTEXT_HEADER_ATTRIBUTE));
|
||||
assertFalse("Security context header found when no security context existed.", header.getAttributeNames()
|
||||
.contains(SecurityContextUtils.SECURITY_CONTEXT_HEADER_ATTRIBUTE));
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void associateContextWithThread(){
|
||||
private void associateContextWithThread() {
|
||||
SecurityContextHolder.setContext(securityContext);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class StubSecurityContext implements SecurityContext{
|
||||
private static class StubSecurityContext implements SecurityContext {
|
||||
|
||||
private Authentication authentication = new Authentication() {
|
||||
|
||||
@@ -113,8 +106,7 @@ public class SecurityContextPropagatingChannelInterceptorTests {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setAuthenticated(boolean isAuthenticated)
|
||||
throws IllegalArgumentException {
|
||||
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
||||
@@ -12,25 +12,25 @@
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
|
||||
|
||||
|
||||
<beans:import resource="commonSecurityConfiguration.xml"/>
|
||||
<beans:import resource="classpath:org/springframework/integration/security/config/commonSecurityConfiguration.xml"/>
|
||||
|
||||
<si-security:secured-channels send-access="ROLE_ADMIN" propagate="false">
|
||||
<si-security:secured-channels send-access="ROLE_ADMIN">
|
||||
<si-security:channel-name-pattern>adminRequiredForSend</si-security:channel-name-pattern>
|
||||
</si-security:secured-channels>
|
||||
|
||||
<si-security:secured-channels send-access="ROLE_ADMIN, ROLE_USER" propagate="false">
|
||||
<si-security:secured-channels send-access="ROLE_ADMIN, ROLE_USER">
|
||||
<si-security:channel-name-pattern>adminOrUserRequiredForSend</si-security:channel-name-pattern>
|
||||
</si-security:secured-channels>
|
||||
|
||||
<si-security:secured-channels receive-access="ROLE_ADMIN" propagate="false">
|
||||
<si-security:secured-channels receive-access="ROLE_ADMIN">
|
||||
<si-security:channel-name-pattern>adminRequiredForReceive</si-security:channel-name-pattern>
|
||||
</si-security:secured-channels>
|
||||
|
||||
<si-security:secured-channels receive-access="ROLE_ADMIN, ROLE_USER" propagate="false">
|
||||
<si-security:secured-channels receive-access="ROLE_ADMIN, ROLE_USER">
|
||||
<si-security:channel-name-pattern>adminOrUserRequiredForReceive</si-security:channel-name-pattern>
|
||||
</si-security:secured-channels>
|
||||
|
||||
<si-security:secured-channels receive-access="ROLE_ADMIN" send-access="ROLE_ADMIN" propagate="false">
|
||||
<si-security:secured-channels receive-access="ROLE_ADMIN" send-access="ROLE_ADMIN">
|
||||
<si-security:channel-name-pattern>adminForSendAndReceive</si-security:channel-name-pattern>
|
||||
</si-security:secured-channels>
|
||||
|
||||
@@ -14,11 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.security.config;
|
||||
package org.springframework.integration.security.channel.config;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -11,23 +11,11 @@
|
||||
http://www.springframework.org/schema/integration-security http://www.springframework.org/schema/integration/spring-integration-security-1.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
|
||||
|
||||
<beans:import resource="commonSecurityConfiguration.xml"/>
|
||||
|
||||
<message-bus/>
|
||||
|
||||
<channel id="propagationDefault"/>
|
||||
|
||||
<si-security:secured-channels send-access="ROLE_ADMIN" >
|
||||
<si-security:channel-name-pattern>adminRequiredForSend</si-security:channel-name-pattern>
|
||||
</si-security:secured-channels>
|
||||
|
||||
|
||||
<si-security:secured-channels propagate="false">
|
||||
<si-security:channel-name-pattern>excludedFromPropagation</si-security:channel-name-pattern>
|
||||
</si-security:secured-channels>
|
||||
|
||||
<channel id="excludedFromPropagation"/>
|
||||
|
||||
|
||||
<si-security:security-propagating-channels propagate-by-default="false">
|
||||
<si-security:propagation-patterns>
|
||||
<si-security:excludePattern>adminSpecial</si-security:excludePattern>
|
||||
<si-security:excludePattern>admin.*</si-security:excludePattern>
|
||||
</si-security:propagation-patterns>
|
||||
</si-security:security-propagating-channels>
|
||||
|
||||
</beans:beans>
|
||||
@@ -11,32 +11,6 @@
|
||||
http://www.springframework.org/schema/integration-security http://www.springframework.org/schema/integration/spring-integration-security-1.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
|
||||
|
||||
<beans:import resource="commonSecurityConfiguration.xml"/>
|
||||
|
||||
<message-bus/>
|
||||
|
||||
<si-security:security-propagating-channels propagate="true"/>
|
||||
|
||||
<channel id="propagationDefault"/>
|
||||
|
||||
<channel id="excludedFromPropagation" />
|
||||
|
||||
<si-security:secured-channels propagate="false">
|
||||
<si-security:channel-name-pattern>excludedFromPropagation</si-security:channel-name-pattern>
|
||||
</si-security:secured-channels>
|
||||
|
||||
<channel id="includedInPropagation" />
|
||||
|
||||
<si-security:secured-channels propagate="true">
|
||||
<si-security:channel-name-pattern>includedInPropagation</si-security:channel-name-pattern>
|
||||
</si-security:secured-channels>
|
||||
|
||||
<security:authentication-provider user-service-ref="userDetailsService"/>
|
||||
|
||||
<security:user-service id="userDetailsService">
|
||||
<security:user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN"/>
|
||||
<security:user name="bob" password="bobspassword" authorities="ROLE_USER"/>
|
||||
</security:user-service>
|
||||
|
||||
<si-security:security-propagating-channels propagate-by-default="true"/>
|
||||
|
||||
</beans:beans>
|
||||
@@ -14,19 +14,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.security.config;
|
||||
package org.springframework.integration.security.channel.config;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.integration.channel.MessageChannel;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.message.StringMessage;
|
||||
import org.springframework.security.context.SecurityContext;
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
@@ -40,15 +37,6 @@ public class SecurityPropagatingChannelsParserTests {
|
||||
|
||||
private ClassPathXmlApplicationContext applicationContext;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("propagationDefault")
|
||||
MessageChannel propagationDefault;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("excludedFromPropagation")
|
||||
MessageChannel excludedFromPropagation;
|
||||
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
if (applicationContext != null) {
|
||||
@@ -57,34 +45,39 @@ public class SecurityPropagatingChannelsParserTests {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testPropagationByDefault() {
|
||||
loadApplicationContext(this.getClass().getSimpleName() + "-propagateByDefaultContext.xml");
|
||||
MessageChannel channel = new QueueChannel();
|
||||
applicationContext.getAutowireCapableBeanFactory().applyBeanPostProcessorsAfterInitialization(channel,
|
||||
"Does not matter");
|
||||
assertTrue("security context did not propagate by setting message bus level default",
|
||||
channelPropagatesSecurityContext(propagationDefault));
|
||||
channelPropagatesSecurityContext(channel));
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void testNoPropagationOnExcludedChannel() {
|
||||
// loadApplicationContext(this.getClass().getSimpleName() +
|
||||
// "-propagateByDefaultContext.xml");
|
||||
// assertFalse("security context propagated when channel was explicitly
|
||||
// excluded",
|
||||
// channelPropagatesSecurityContext(excludedFromPropagation));
|
||||
// }
|
||||
//
|
||||
@Test
|
||||
public void testNoPropagationOnExcludedChannel() {
|
||||
loadApplicationContext(this.getClass().getSimpleName() + "-propagateByDefaultContext.xml");
|
||||
assertFalse("security context propagated when channel was explicitly excluded",
|
||||
channelPropagatesSecurityContext(excludedFromPropagation));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoPropagationWithNoDefaultPropagation() {
|
||||
public void testNoPropagationWithExcludedChannel() {
|
||||
loadApplicationContext(this.getClass().getSimpleName() + "-noPropagationByDefaultContext.xml");
|
||||
assertFalse("security context propagated when channel default was false and no secured tag present",
|
||||
channelPropagatesSecurityContext(propagationDefault));
|
||||
MessageChannel channel = new QueueChannel();
|
||||
applicationContext.getAutowireCapableBeanFactory().applyBeanPostProcessorsAfterInitialization(channel,
|
||||
"adminSpecial");
|
||||
assertFalse("security context propagated when channel excluded", channelPropagatesSecurityContext(channel));
|
||||
}
|
||||
|
||||
|
||||
private boolean channelPropagatesSecurityContext(MessageChannel channel) {
|
||||
login("bob", "bobspassword");
|
||||
channel.send(new StringMessage("testMessage"));
|
||||
SecurityContext context = (SecurityContext)
|
||||
channel.receive(-1).getHeader().getAttribute("SPRING_SECURITY_CONTEXT");
|
||||
SecurityContext context = (SecurityContext) channel.receive(-1).getHeader().getAttribute(
|
||||
"SPRING_SECURITY_CONTEXT");
|
||||
return context != null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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.integration.security.config;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.StringReader;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
public class IncludeExcludePatternParserTests {
|
||||
|
||||
IncludeExcludePatternParser patternParser;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
patternParser = new IncludeExcludePatternParser();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleIncludeWithIncludeByDefaultFalse() throws Exception {
|
||||
NodeList nodeList = getNodeList("<doc><includePattern>includeMe</includePattern><excludePattern>.*</excludePattern></doc>");
|
||||
OrderedIncludeExcludeList matcher = patternParser.createFromNodeList(false, nodeList);
|
||||
assertTrue("Did not match expected entry includeMe", matcher.isIncluded("includeMe"));
|
||||
assertFalse("Matched unexpected entry notMe", matcher.isIncluded("notMe"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncludeByDefaultTrue() throws Exception {
|
||||
NodeList nodeList = getNodeList("<doc></doc>");
|
||||
OrderedIncludeExcludeList matcher = patternParser.createFromNodeList(true, nodeList);
|
||||
assertTrue("Did not match expected entry includeMe", matcher.isIncluded("anything"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncludeByDefaultTrueButExcluded() throws Exception {
|
||||
NodeList nodeList = getNodeList("<doc><excludePattern>ex.*</excludePattern><includePattern>exShouldNotMatter</includePattern></doc>");
|
||||
OrderedIncludeExcludeList matcher = patternParser.createFromNodeList(true, nodeList);
|
||||
assertFalse("Matched unexpected entry exNotMe", matcher.isIncluded("exNotMe"));
|
||||
assertFalse("Matched unexpected entry exShouldNotMatter", matcher.isIncluded("exShouldNotMatter"));
|
||||
}
|
||||
|
||||
public NodeList getNodeList(String xmlString) throws Exception {
|
||||
StringReader reader = new StringReader(xmlString);
|
||||
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(reader));
|
||||
return doc.getDocumentElement().getChildNodes();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,19 +1,31 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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.integration.security.config;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jonas Partner
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class JdkRegExpOrderedIncludeExcludeListTests {
|
||||
|
||||
@@ -39,15 +51,15 @@ public class JdkRegExpOrderedIncludeExcludeListTests {
|
||||
assertFalse("Unexpected match when match by default false and no patterns", matcher.isIncluded("anyoldthing"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testExcludeThenIncludeWithIncludeByDefaultFalse() {
|
||||
List<IncludeExcludePattern> patterns = createIncludeExcludeList(new boolean[] {false, true}, new String[] {"admin.*",".*"});
|
||||
List<IncludeExcludePattern> patterns = createIncludeExcludeList(new boolean[] { false, true }, new String[] {
|
||||
"admin.*", ".*" });
|
||||
JdkRegExpOrderedIncludeExcludeList matcher = new JdkRegExpOrderedIncludeExcludeList(false, patterns);
|
||||
assertFalse("Unexpected match when match by default false and should have been excluded", matcher.isIncluded("adminChannel"));
|
||||
assertFalse("Unexpected match when match by default false and should have been excluded", matcher
|
||||
.isIncluded("adminChannel"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
List<IncludeExcludePattern> createIncludeExcludeList(boolean[] includeExclude, String[] patterns) {
|
||||
assertEquals("flag and patterns arrays must be same length", includeExclude.length, patterns.length);
|
||||
|
||||
|
||||
@@ -24,20 +24,21 @@ import org.springframework.security.providers.UsernamePasswordAuthenticationToke
|
||||
/**
|
||||
*
|
||||
* @author Jonas Partner
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class SecurityTestUtil {
|
||||
|
||||
public static SecurityContext createContext(String username, String password, String... roles){
|
||||
|
||||
public static SecurityContext createContext(String username, String password, String... roles) {
|
||||
SecurityContextImpl ctxImpl = new SecurityContextImpl();
|
||||
UsernamePasswordAuthenticationToken authToken;
|
||||
if(roles != null && roles.length > 0){
|
||||
if (roles != null && roles.length > 0) {
|
||||
GrantedAuthority[] authorities = new GrantedAuthority[roles.length];
|
||||
for (int i =0; i < roles.length; i++) {
|
||||
for (int i = 0; i < roles.length; i++) {
|
||||
authorities[i] = new GrantedAuthorityImpl(roles[i]);
|
||||
}
|
||||
authToken = new UsernamePasswordAuthenticationToken(username,password,authorities);
|
||||
} else {
|
||||
authToken = new UsernamePasswordAuthenticationToken(username, password, authorities);
|
||||
}
|
||||
else {
|
||||
authToken = new UsernamePasswordAuthenticationToken(username, password);
|
||||
}
|
||||
ctxImpl.setAuthentication(authToken);
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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.integration.security.endpoint;
|
||||
|
||||
import static org.easymock.EasyMock.*;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.junit.Test;
|
||||
import org.springframework.integration.message.Message;
|
||||
import org.springframework.integration.message.StringMessage;
|
||||
import org.springframework.integration.security.SecurityContextUtils;
|
||||
import org.springframework.integration.security.config.SecurityTestUtil;
|
||||
import org.springframework.security.AccessDecisionManager;
|
||||
import org.springframework.security.AccessDeniedException;
|
||||
import org.springframework.security.ConfigAttributeDefinition;
|
||||
import org.springframework.security.context.SecurityContext;
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jonas Partner
|
||||
*
|
||||
*/
|
||||
public class SecurityEndpointInterceptorTests {
|
||||
|
||||
@Test(expected = AccessDeniedException.class)
|
||||
public void testUnauthenticatedAccessToSecuredEndpointWithNullMessage() throws Throwable {
|
||||
try {
|
||||
Object target = new Object();
|
||||
MethodInvocation invocation = createTestMethodInvocationWithNullMessage(target);
|
||||
ConfigAttributeDefinition attDefintion = new ConfigAttributeDefinition("ROLE_ADMIN");
|
||||
AccessDecisionManager adm = createMock(AccessDecisionManager.class);
|
||||
adm.decide(null, target, attDefintion);
|
||||
expectLastCall().andThrow(new AccessDeniedException("nope"));
|
||||
|
||||
replay(invocation);
|
||||
replay(adm);
|
||||
|
||||
SecurityEndpointInterceptor interceptor = new SecurityEndpointInterceptor(attDefintion, adm);
|
||||
interceptor.aroundInvoke(invocation);
|
||||
|
||||
verify(invocation, adm);
|
||||
}
|
||||
finally {
|
||||
assertNull("Authentication was not null after invocation threw AccessDeniedException",
|
||||
SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = AccessDeniedException.class)
|
||||
public void testUnauthenticatedAccessToSecuredEndpoint() throws Throwable {
|
||||
try {
|
||||
Object target = new Object();
|
||||
MethodInvocation invocation = createTestMethodInvocationNoSecurityHeaderInMessage(target);
|
||||
ConfigAttributeDefinition attDefintion = new ConfigAttributeDefinition("ROLE_ADMIN");
|
||||
AccessDecisionManager adm = createMock(AccessDecisionManager.class);
|
||||
adm.decide(null, target, attDefintion);
|
||||
expectLastCall().andThrow(new AccessDeniedException("nope"));
|
||||
|
||||
replay(invocation);
|
||||
replay(adm);
|
||||
|
||||
SecurityEndpointInterceptor interceptor = new SecurityEndpointInterceptor(attDefintion, adm);
|
||||
interceptor.aroundInvoke(invocation);
|
||||
|
||||
verify(invocation, adm);
|
||||
}
|
||||
finally {
|
||||
assertNull("Authentication was not null after invocation threw AccessDeniedException",
|
||||
SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAuthenticatedAccessToSecuredEndpoint() throws Throwable {
|
||||
try {
|
||||
Object target = new Object();
|
||||
SecurityContext context = SecurityTestUtil.createContext("bob", "bobspassword",
|
||||
new String[] { "ROLE_ADMIN" });
|
||||
MethodInvocation invocation = createTestMethodInvocation(target, context);
|
||||
expect(invocation.proceed()).andReturn(null);
|
||||
replay(invocation);
|
||||
|
||||
ConfigAttributeDefinition attDefintion = new ConfigAttributeDefinition("ROLE_ADMIN");
|
||||
|
||||
AccessDecisionManager adm = createMock(AccessDecisionManager.class);
|
||||
adm.decide(context.getAuthentication(), target, attDefintion);
|
||||
expectLastCall();
|
||||
replay(adm);
|
||||
|
||||
SecurityEndpointInterceptor interceptor = new SecurityEndpointInterceptor(attDefintion, adm);
|
||||
interceptor.aroundInvoke(invocation);
|
||||
|
||||
verify(invocation, adm);
|
||||
|
||||
}
|
||||
finally {
|
||||
assertNull("Authentication was not null after successful invocation", SecurityContextHolder.getContext()
|
||||
.getAuthentication());
|
||||
}
|
||||
}
|
||||
|
||||
public MethodInvocation createTestMethodInvocation(Object target, SecurityContext securityContext) {
|
||||
Message message = new StringMessage("test");
|
||||
SecurityContextUtils.setSecurityContextHeader(securityContext, message);
|
||||
MethodInvocation mockInvocation = createMock(MethodInvocation.class);
|
||||
expect(mockInvocation.getArguments()).andReturn(new Object[] { message });
|
||||
expect(mockInvocation.getThis()).andReturn(target);
|
||||
return mockInvocation;
|
||||
}
|
||||
|
||||
public MethodInvocation createTestMethodInvocationNoSecurityHeaderInMessage(Object target) {
|
||||
Message message = new StringMessage("test");
|
||||
MethodInvocation mockInvocation = createMock(MethodInvocation.class);
|
||||
expect(mockInvocation.getArguments()).andReturn(new Object[] { message });
|
||||
expect(mockInvocation.getThis()).andReturn(target);
|
||||
return mockInvocation;
|
||||
}
|
||||
|
||||
public MethodInvocation createTestMethodInvocationWithNullMessage(Object target) {
|
||||
MethodInvocation mockInvocation = createMock(MethodInvocation.class);
|
||||
expect(mockInvocation.getArguments()).andReturn(new Object[] { null });
|
||||
expect(mockInvocation.getThis()).andReturn(target);
|
||||
return mockInvocation;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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.integration.security.target;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.integration.message.BlockingTarget;
|
||||
import org.springframework.integration.message.Message;
|
||||
import org.springframework.integration.message.StringMessage;
|
||||
import org.springframework.integration.message.Target;
|
||||
import org.springframework.integration.security.target.TargetSecuringAdvisor;
|
||||
import org.springframework.security.AccessDecisionManager;
|
||||
import org.springframework.security.AccessDeniedException;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.ConfigAttribute;
|
||||
import org.springframework.security.ConfigAttributeDefinition;
|
||||
import org.springframework.security.InsufficientAuthenticationException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jonas Partner
|
||||
*
|
||||
*/
|
||||
public class TargetSecuringAdvisorTests {
|
||||
|
||||
public Object proxy(Object target, TargetSecuringAdvisor advisor) {
|
||||
ProxyFactory proxyFactory = new ProxyFactory(target);
|
||||
proxyFactory.addAdvisor(advisor);
|
||||
|
||||
return proxyFactory.getProxy();
|
||||
|
||||
}
|
||||
|
||||
@Test(expected = AccessDeniedException.class)
|
||||
public void testTargetSendAdvised() {
|
||||
TargetSecuringAdvisor advisor = new TargetSecuringAdvisor(new AlwaysDenyAccessDecisionManager(), "ROLE_ADMIN");
|
||||
Target target = (Target) proxy(new TestTarget(), advisor);
|
||||
target.send(new StringMessage("test"));
|
||||
}
|
||||
|
||||
@Test(expected = AccessDeniedException.class)
|
||||
public void testBlockingTargetSendAdvised() {
|
||||
TargetSecuringAdvisor advisor = new TargetSecuringAdvisor(new AlwaysDenyAccessDecisionManager(), "ROLE_ADMIN");
|
||||
Target target = (Target) proxy(new BlockingTestTarget(), advisor);
|
||||
target.send(new StringMessage("test"));
|
||||
}
|
||||
|
||||
@Test(expected = AccessDeniedException.class)
|
||||
public void testBlockingTargetSendWithTimeoutAdvised() {
|
||||
TargetSecuringAdvisor advisor = new TargetSecuringAdvisor(new AlwaysDenyAccessDecisionManager(), "ROLE_ADMIN");
|
||||
BlockingTarget target = (BlockingTarget) proxy(new BlockingTestTarget(), advisor);
|
||||
target.send(new StringMessage("test"), 10l);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTargetSendNotFromTargetInterface() {
|
||||
TargetSecuringAdvisor advisor = new TargetSecuringAdvisor(new AlwaysDenyAccessDecisionManager(), "ROLE_ADMIN");
|
||||
OtherSend target = (OtherSend) proxy(new TestTarget(), advisor);
|
||||
target.send(10l);
|
||||
}
|
||||
|
||||
static interface OtherSend {
|
||||
|
||||
public void send(long l);
|
||||
}
|
||||
|
||||
static class AlwaysDenyAccessDecisionManager implements AccessDecisionManager {
|
||||
|
||||
public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config)
|
||||
throws AccessDeniedException, InsufficientAuthenticationException {
|
||||
throw new AccessDeniedException("dave");
|
||||
}
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean supports(Class clazz) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class TestTarget implements Target, OtherSend {
|
||||
|
||||
boolean invoked;
|
||||
|
||||
public boolean send(Message<?> message) {
|
||||
invoked = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void send(long a) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class BlockingTestTarget implements BlockingTarget {
|
||||
|
||||
boolean invoked;
|
||||
|
||||
public boolean send(Message<?> message) {
|
||||
invoked = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void send() {
|
||||
}
|
||||
|
||||
public boolean send(Message<?> message, long timeout) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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.integration.security.target;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.integration.message.Message;
|
||||
import org.springframework.integration.message.StringMessage;
|
||||
import org.springframework.integration.message.Target;
|
||||
import org.springframework.integration.security.SecurityContextUtils;
|
||||
import org.springframework.integration.security.config.SecurityTestUtil;
|
||||
import org.springframework.integration.security.target.TargetSecuringInterceptor;
|
||||
import org.springframework.security.AccessDecisionManager;
|
||||
import org.springframework.security.AccessDeniedException;
|
||||
import org.springframework.security.ConfigAttributeDefinition;
|
||||
import org.springframework.security.context.SecurityContext;
|
||||
import org.springframework.security.vote.AccessDecisionVoter;
|
||||
import org.springframework.security.vote.AuthenticatedVoter;
|
||||
import org.springframework.security.vote.RoleVoter;
|
||||
import org.springframework.security.vote.UnanimousBased;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jonas Partner
|
||||
*
|
||||
*/
|
||||
public class TargetSecuringInterceptorTests {
|
||||
|
||||
|
||||
UnanimousBased accessDecisionManager;
|
||||
|
||||
@Before
|
||||
public void setup(){
|
||||
accessDecisionManager = new UnanimousBased();
|
||||
List<AccessDecisionVoter> voterList = new ArrayList<AccessDecisionVoter>();
|
||||
voterList.add(new AuthenticatedVoter());
|
||||
voterList.add(new RoleVoter());
|
||||
accessDecisionManager.setDecisionVoters(voterList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Object createProxy(Object target,String securityAttributes, AccessDecisionManager accessDecisionManager){
|
||||
TargetSecuringInterceptor interceptor = new TargetSecuringInterceptor(new ConfigAttributeDefinition(StringUtils.tokenizeToStringArray(securityAttributes,",")), accessDecisionManager);
|
||||
ProxyFactory factory = new ProxyFactory(target);
|
||||
factory.addAdvice(interceptor);
|
||||
return factory.getProxy();
|
||||
}
|
||||
|
||||
@Test(expected=AccessDeniedException.class)
|
||||
public void testAccessDenied(){
|
||||
Target proxiedTarget = (Target) createProxy(new TestTarget(), "IS_AUTHENTICATED_FULLY, ROLE_ADMIN", accessDecisionManager);
|
||||
SecurityContext sctx = SecurityTestUtil.createContext("bob", "password", "IS_AUTHENTICATED_ANONYMOUSLY", "ROLE_USER");
|
||||
StringMessage message = new StringMessage("test");
|
||||
SecurityContextUtils.setSecurityContextHeader(sctx, message);
|
||||
proxiedTarget.send(message);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccessGranted(){
|
||||
Target proxiedTarget = (Target) createProxy(new TestTarget(), "IS_AUTHENTICATED_FULLY, ROLE_ADMIN", accessDecisionManager);
|
||||
SecurityContext sctx = SecurityTestUtil.createContext("bob", "password", "IS_AUTHENTICATED_ANONYMOUSLY", "ROLE_USER", "ROLE_ADMIN");
|
||||
StringMessage message = new StringMessage("test");
|
||||
SecurityContextUtils.setSecurityContextHeader(sctx, message);
|
||||
proxiedTarget.send(message);
|
||||
}
|
||||
|
||||
|
||||
@Test(expected=RuntimeException.class)
|
||||
public void testNotAuthenticated(){
|
||||
Target proxiedTarget = (Target) createProxy(new TestTarget(), "IS_AUTHENTICATED_FULLY, ROLE_ADMIN", accessDecisionManager);
|
||||
StringMessage message = new StringMessage("test");
|
||||
proxiedTarget.send(message);
|
||||
}
|
||||
|
||||
|
||||
static class TestTarget implements Target{
|
||||
|
||||
boolean invoked;
|
||||
|
||||
public boolean send(Message<?> message) {
|
||||
invoked = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void send(long l) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user