interceptor for securing endpoints based on new endpoint interception model
namespace support to follow
This commit is contained in:
@@ -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