interceptor for securing endpoints based on new endpoint interception model

namespace support to follow
This commit is contained in:
Jonas Partner
2008-06-27 17:47:17 +00:00
parent 8623920db5
commit f9ad394850
33 changed files with 493 additions and 969 deletions

View File

@@ -33,7 +33,7 @@ import org.springframework.integration.message.selector.MessageSelector;
/**
*
* @author Jonas Partner
*
*
*/
public class ChannelInterceptorRegisteringBeanPostProcessorTests {

View File

@@ -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;
}
}
}

View File

@@ -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() {

View File

@@ -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>

View File

@@ -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;

View File

@@ -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>

View File

@@ -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>

View File

@@ -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;
}

View File

@@ -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();
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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;
}
}
}

View File

@@ -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
}
}
}