GH-3897: Deprecate ChannelSecurityInterceptor (#3915)
* GH-3897: Deprecate `ChannelSecurityInterceptor` Fixes https://github.com/spring-projects/spring-integration/issues/3897 Spring Security has deprecated `AccessDecisionManager` and all its infrastructure in favor of `AuthorizationManager` * Deprecate and AOP `ChannelSecurityInterceptor` and all its infrastructure, including `@SecuredChannel` and respective XML configuration. The `AuthorizationChannelInterceptor` added to respective channels for security or configured as a global channel interceptor fully covers the previous AOP configuration * Fix deprecation warnings in other tests with security * Fix language in docs Co-authored-by: Gary Russell <grussell@vmware.com> * * Remove `forRemoval` attr from `@Deprecated` markers for Security classes: looks like to mark `@Deprecated` and even `@SuppressWarnings("deprecation")` don't silence warnings on compilation Co-authored-by: Gary Russell <grussell@vmware.com>
This commit is contained in:
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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
|
||||
*
|
||||
* https://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.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
public class MockAuthenticationManager implements AuthenticationManager {
|
||||
|
||||
private final boolean grantAccess;
|
||||
|
||||
public MockAuthenticationManager(boolean grantAccess) {
|
||||
this.grantAccess = grantAccess;
|
||||
}
|
||||
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
if (this.grantAccess) {
|
||||
authentication.setAuthenticated(true);
|
||||
}
|
||||
return authentication;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,22 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/integration"
|
||||
xmlns:si-security="http://www.springframework.org/schema/integration/security"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:task="http://www.springframework.org/schema/task"
|
||||
xmlns:security="http://www.springframework.org/schema/security"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
https://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration
|
||||
https://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/integration/security
|
||||
https://www.springframework.org/schema/integration/security/spring-integration-security.xsd
|
||||
http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd
|
||||
http://www.springframework.org/schema/task https://www.springframework.org/schema/task/spring-task.xsd">
|
||||
|
||||
<beans:import resource="classpath:org/springframework/integration/security/config/commonSecurityConfiguration.xml"/>
|
||||
<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:secured-channels>
|
||||
<si-security:access-policy pattern="securedChannel.*" send-access="ROLE_ADMIN, ROLE_PRESIDENT"/>
|
||||
</si-security:secured-channels>
|
||||
<channel-interceptor pattern="securedChannel*">
|
||||
<beans:bean
|
||||
class="org.springframework.security.messaging.access.intercept.AuthorizationChannelInterceptor">
|
||||
<beans:constructor-arg>
|
||||
<beans:bean class="org.springframework.security.authorization.AuthorityAuthorizationManager"
|
||||
factory-method="hasAnyRole">
|
||||
<beans:constructor-arg>
|
||||
<beans:array>
|
||||
<beans:value>ADMIN</beans:value>
|
||||
<beans:value>PRESIDENT</beans:value>
|
||||
</beans:array>
|
||||
</beans:constructor-arg>
|
||||
</beans:bean>
|
||||
</beans:constructor-arg>
|
||||
</beans:bean>
|
||||
</channel-interceptor>
|
||||
|
||||
<beans:bean id="testHandler" class="org.springframework.integration.security.TestHandler"/>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -17,10 +17,10 @@
|
||||
package org.springframework.integration.security.channel;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
@@ -28,25 +28,22 @@ import org.springframework.integration.security.SecurityTestUtils;
|
||||
import org.springframework.integration.security.TestHandler;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageHandlingException;
|
||||
import org.springframework.messaging.MessageDeliveryException;
|
||||
import org.springframework.messaging.PollableChannel;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringJUnitConfig
|
||||
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
|
||||
public class ChannelAdapterSecurityIntegrationTests {
|
||||
|
||||
@@ -78,59 +75,67 @@ public class ChannelAdapterSecurityIntegrationTests {
|
||||
TestHandler testConsumer;
|
||||
|
||||
|
||||
@After
|
||||
@AfterEach
|
||||
public void tearDown() {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = AccessDeniedException.class)
|
||||
@Test
|
||||
public void testSecuredWithNotEnoughPermission() {
|
||||
login("bob", "bobspassword", "ROLE_ADMINA");
|
||||
securedChannelAdapter.send(new GenericMessage<String>("test"));
|
||||
assertThatExceptionOfType(MessageDeliveryException.class)
|
||||
.isThrownBy(() -> this.securedChannelAdapter.send(new GenericMessage<>("test")))
|
||||
.withRootCauseExactlyInstanceOf(AccessDeniedException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSecuredWithPermission() {
|
||||
login("bob", "bobspassword", "ROLE_ADMIN", "ROLE_PRESIDENT");
|
||||
securedChannelAdapter.send(new GenericMessage<String>("test"));
|
||||
securedChannelAdapter2.send(new GenericMessage<String>("test"));
|
||||
securedChannelAdapter.send(new GenericMessage<>("test"));
|
||||
securedChannelAdapter2.send(new GenericMessage<>("test"));
|
||||
assertThat(testConsumer.sentMessages.size()).as("Wrong size of message list in target").isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSecurityContextPropagation() {
|
||||
login("bob", "bobspassword", "ROLE_ADMIN", "ROLE_PRESIDENT");
|
||||
this.queueChannel.send(new GenericMessage<String>("test"));
|
||||
this.queueChannel.send(new GenericMessage<>("test"));
|
||||
Message<?> receive = this.securedChannelQueue.receive(10000);
|
||||
assertThat(receive).isNotNull();
|
||||
|
||||
SecurityContextHolder.clearContext();
|
||||
|
||||
this.queueChannel.send(new GenericMessage<String>("test"));
|
||||
this.queueChannel.send(new GenericMessage<>("test"));
|
||||
Message<?> errorMessage = this.errorChannel.receive(10000);
|
||||
assertThat(errorMessage).isNotNull();
|
||||
Object payload = errorMessage.getPayload();
|
||||
assertThat(payload).isInstanceOf(MessageHandlingException.class);
|
||||
assertThat(((MessageHandlingException) payload).getCause())
|
||||
assertThat(payload).isInstanceOf(MessageDeliveryException.class);
|
||||
assertThat(((MessageDeliveryException) payload).getCause())
|
||||
.isInstanceOf(AuthenticationCredentialsNotFoundException.class);
|
||||
}
|
||||
|
||||
@Test(expected = AccessDeniedException.class)
|
||||
@Test
|
||||
public void testSecuredWithoutPermission() {
|
||||
login("bob", "bobspassword", "ROLE_USER");
|
||||
securedChannelAdapter.send(new GenericMessage<String>("test"));
|
||||
assertThatExceptionOfType(MessageDeliveryException.class)
|
||||
.isThrownBy(() -> this.securedChannelAdapter.send(new GenericMessage<>("test")))
|
||||
.withRootCauseExactlyInstanceOf(AccessDeniedException.class);
|
||||
}
|
||||
|
||||
@Test(expected = AccessDeniedException.class)
|
||||
@Test
|
||||
public void testSecured2WithoutPermission() {
|
||||
login("bob", "bobspassword", "ROLE_USER");
|
||||
securedChannelAdapter2.send(new GenericMessage<String>("test"));
|
||||
assertThatExceptionOfType(MessageDeliveryException.class)
|
||||
.isThrownBy(() -> this.securedChannelAdapter2.send(new GenericMessage<>("test")))
|
||||
.withRootCauseExactlyInstanceOf(AccessDeniedException.class);
|
||||
}
|
||||
|
||||
@Test(expected = AuthenticationException.class)
|
||||
@Test
|
||||
public void testSecuredWithoutAuthenticating() {
|
||||
securedChannelAdapter.send(new GenericMessage<String>("test"));
|
||||
assertThatExceptionOfType(MessageDeliveryException.class)
|
||||
.isThrownBy(() -> this.securedChannelAdapter.send(new GenericMessage<>("test")))
|
||||
.withRootCauseExactlyInstanceOf(AuthenticationCredentialsNotFoundException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -16,80 +16,67 @@
|
||||
|
||||
package org.springframework.integration.security.channel;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.security.MockAuthenticationManager;
|
||||
import org.springframework.integration.security.SecurityTestUtils;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageDeliveryException;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.access.vote.AffirmativeBased;
|
||||
import org.springframework.security.access.vote.RoleVoter;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
|
||||
import org.springframework.security.authorization.AuthorityAuthorizationManager;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.messaging.access.intercept.AuthorizationChannelInterceptor;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
public class ChannelSecurityInterceptorTests {
|
||||
|
||||
@After
|
||||
@AfterEach
|
||||
public void clearSecurityContext() {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
@Test(expected = AuthenticationException.class)
|
||||
public void securedSendWithoutAuthentication() throws Exception {
|
||||
MessageChannel channel = getSecuredChannel("ROLE_ADMIN");
|
||||
channel.send(new GenericMessage<String>("test"));
|
||||
}
|
||||
|
||||
@Test(expected = AccessDeniedException.class)
|
||||
public void securedSendWithoutRole() throws Exception {
|
||||
MessageChannel channel = getSecuredChannel("ROLE_ADMIN");
|
||||
SecurityContext context = SecurityTestUtils.createContext("test", "pwd", "ROLE_USER");
|
||||
SecurityContextHolder.setContext(context);
|
||||
channel.send(new GenericMessage<String>("test"));
|
||||
@Test
|
||||
public void securedSendWithoutAuthentication() {
|
||||
MessageChannel channel = getSecuredChannel();
|
||||
assertThatExceptionOfType(MessageDeliveryException.class)
|
||||
.isThrownBy(() -> channel.send(new GenericMessage<>("test")))
|
||||
.withRootCauseExactlyInstanceOf(AuthenticationCredentialsNotFoundException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void securedSendWithRole() throws Exception {
|
||||
MessageChannel channel = getSecuredChannel("ROLE_ADMIN");
|
||||
public void securedSendWithoutRole() {
|
||||
MessageChannel channel = getSecuredChannel();
|
||||
SecurityContext context = SecurityTestUtils.createContext("test", "pwd", "ROLE_USER");
|
||||
SecurityContextHolder.setContext(context);
|
||||
assertThatExceptionOfType(MessageDeliveryException.class)
|
||||
.isThrownBy(() -> channel.send(new GenericMessage<>("test")))
|
||||
.withRootCauseExactlyInstanceOf(AccessDeniedException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void securedSendWithRole() {
|
||||
MessageChannel channel = getSecuredChannel();
|
||||
SecurityContext context = SecurityTestUtils.createContext("test", "pwd", "ROLE_ADMIN");
|
||||
SecurityContextHolder.setContext(context);
|
||||
channel.send(new GenericMessage<String>("test"));
|
||||
channel.send(new GenericMessage<>("test"));
|
||||
}
|
||||
|
||||
|
||||
private static MessageChannel getSecuredChannel(String role) throws Exception {
|
||||
private static MessageChannel getSecuredChannel() {
|
||||
QueueChannel channel = new QueueChannel();
|
||||
channel.setBeanName("securedChannel");
|
||||
ProxyFactory proxyFactory = new ProxyFactory(channel);
|
||||
proxyFactory.addAdvice(createInterceptor(role));
|
||||
return (MessageChannel) proxyFactory.getProxy();
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static ChannelSecurityInterceptor createInterceptor(String role) throws Exception {
|
||||
ChannelSecurityMetadataSource securityMetadataSource = new ChannelSecurityMetadataSource();
|
||||
securityMetadataSource.addPatternMapping(Pattern.compile("secured.*"), new DefaultChannelAccessPolicy(role, null));
|
||||
ChannelSecurityInterceptor interceptor = new ChannelSecurityInterceptor(securityMetadataSource);
|
||||
AffirmativeBased accessDecisionManager = AffirmativeBased.class.getConstructor(List.class)
|
||||
.newInstance(Collections.singletonList(new RoleVoter()));
|
||||
accessDecisionManager.afterPropertiesSet();
|
||||
interceptor.setAccessDecisionManager(accessDecisionManager);
|
||||
interceptor.setAuthenticationManager(new MockAuthenticationManager(true));
|
||||
interceptor.afterPropertiesSet();
|
||||
return interceptor;
|
||||
channel.addInterceptor(new AuthorizationChannelInterceptor(AuthorityAuthorizationManager.hasRole("ADMIN")));
|
||||
return channel;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2019 the original author or authors.
|
||||
* Copyright 2014-2022 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.
|
||||
@@ -17,20 +17,19 @@
|
||||
package org.springframework.integration.security.config;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportResource;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
@@ -50,13 +49,11 @@ import org.springframework.integration.config.GlobalChannelInterceptor;
|
||||
import org.springframework.integration.handler.BridgeHandler;
|
||||
import org.springframework.integration.security.SecurityTestUtils;
|
||||
import org.springframework.integration.security.TestHandler;
|
||||
import org.springframework.integration.security.channel.ChannelSecurityInterceptor;
|
||||
import org.springframework.integration.security.channel.SecuredChannel;
|
||||
import org.springframework.integration.security.channel.SecurityContextPropagationChannelInterceptor;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageDeliveryException;
|
||||
import org.springframework.messaging.MessageHandler;
|
||||
import org.springframework.messaging.MessageHandlingException;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.messaging.PollableChannel;
|
||||
import org.springframework.messaging.SubscribableChannel;
|
||||
@@ -64,27 +61,27 @@ import org.springframework.messaging.support.ChannelInterceptor;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.security.access.AccessDecisionManager;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.authorization.AuthorityAuthorizationManager;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.messaging.access.intercept.AuthorizationChannelInterceptor;
|
||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
import org.springframework.security.task.DelegatingSecurityContextAsyncTaskExecutor;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
|
||||
/**
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@SpringJUnitConfig
|
||||
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
|
||||
public class ChannelSecurityInterceptorSecuredChannelAnnotationTests {
|
||||
public class ChannelSecurityAnnotationTests {
|
||||
|
||||
@Autowired
|
||||
MessageChannel securedChannel;
|
||||
@@ -125,96 +122,104 @@ public class ChannelSecurityInterceptorSecuredChannelAnnotationTests {
|
||||
@Autowired
|
||||
TestGateway testGateway;
|
||||
|
||||
@After
|
||||
@AfterEach
|
||||
public void tearDown() {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = AccessDeniedException.class)
|
||||
@Test
|
||||
public void testSecuredWithNotEnoughPermission() {
|
||||
login("bob", "bobspassword", "ROLE_ADMINA");
|
||||
securedChannel.send(new GenericMessage<String>("test"));
|
||||
assertThatExceptionOfType(MessageDeliveryException.class)
|
||||
.isThrownBy(() -> this.securedChannel.send(new GenericMessage<>("test")))
|
||||
.withRootCauseExactlyInstanceOf(AccessDeniedException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSecuredWithPermission() {
|
||||
login("bob", "bobspassword", "ROLE_ADMIN", "ROLE_PRESIDENT");
|
||||
securedChannel.send(new GenericMessage<String>("test"));
|
||||
securedChannel2.send(new GenericMessage<String>("test"));
|
||||
securedChannel.send(new GenericMessage<>("test"));
|
||||
securedChannel2.send(new GenericMessage<>("test"));
|
||||
assertThat(testConsumer.sentMessages.size()).as("Wrong size of message list in target").isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test(expected = AccessDeniedException.class)
|
||||
@Test
|
||||
public void testSecuredWithoutPermision() {
|
||||
login("bob", "bobspassword", "ROLE_USER");
|
||||
securedChannel.send(new GenericMessage<String>("test"));
|
||||
assertThatExceptionOfType(MessageDeliveryException.class)
|
||||
.isThrownBy(() -> this.securedChannel.send(new GenericMessage<>("test")))
|
||||
.withRootCauseExactlyInstanceOf(AccessDeniedException.class);
|
||||
}
|
||||
|
||||
@Test(expected = AccessDeniedException.class)
|
||||
@Test
|
||||
public void testSecured2WithoutPermision() {
|
||||
login("bob", "bobspassword", "ROLE_USER");
|
||||
securedChannel2.send(new GenericMessage<String>("test"));
|
||||
assertThatExceptionOfType(MessageDeliveryException.class)
|
||||
.isThrownBy(() -> this.securedChannel2.send(new GenericMessage<>("test")))
|
||||
.withRootCauseExactlyInstanceOf(AccessDeniedException.class);
|
||||
}
|
||||
|
||||
@Test(expected = AuthenticationException.class)
|
||||
@Test
|
||||
public void testSecuredWithoutAuthenticating() {
|
||||
securedChannel.send(new GenericMessage<String>("test"));
|
||||
assertThatExceptionOfType(MessageDeliveryException.class)
|
||||
.isThrownBy(() -> this.securedChannel2.send(new GenericMessage<>("test")))
|
||||
.withRootCauseExactlyInstanceOf(AuthenticationCredentialsNotFoundException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnsecuredAsAdmin() {
|
||||
login("bob", "bobspassword", "ROLE_ADMIN");
|
||||
unsecuredChannel.send(new GenericMessage<String>("test"));
|
||||
unsecuredChannel.send(new GenericMessage<>("test"));
|
||||
assertThat(testConsumer.sentMessages.size()).as("Wrong size of message list in target").isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnsecuredAsUser() {
|
||||
login("bob", "bobspassword", "ROLE_USER");
|
||||
unsecuredChannel.send(new GenericMessage<String>("test"));
|
||||
unsecuredChannel.send(new GenericMessage<>("test"));
|
||||
assertThat(testConsumer.sentMessages.size()).as("Wrong size of message list in target").isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnsecuredWithoutAuthenticating() {
|
||||
unsecuredChannel.send(new GenericMessage<String>("test"));
|
||||
unsecuredChannel.send(new GenericMessage<>("test"));
|
||||
assertThat(testConsumer.sentMessages.size()).as("Wrong size of message list in target").isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSecurityContextPropagationQueueChannel() {
|
||||
login("bob", "bobspassword", "ROLE_ADMIN", "ROLE_PRESIDENT");
|
||||
this.queueChannel.send(new GenericMessage<String>("test"));
|
||||
this.queueChannel.send(new GenericMessage<>("test"));
|
||||
Message<?> receive = this.securedChannelQueue.receive(10000);
|
||||
assertThat(receive).isNotNull();
|
||||
|
||||
SecurityContextHolder.clearContext();
|
||||
|
||||
this.queueChannel.send(new GenericMessage<String>("test"));
|
||||
this.queueChannel.send(new GenericMessage<>("test"));
|
||||
Message<?> errorMessage = this.errorChannel.receive(10000);
|
||||
assertThat(errorMessage).isNotNull();
|
||||
Object payload = errorMessage.getPayload();
|
||||
assertThat(payload).isInstanceOf(MessageHandlingException.class);
|
||||
assertThat(((MessageHandlingException) payload).getCause())
|
||||
assertThat(payload).isInstanceOf(MessageDeliveryException.class);
|
||||
assertThat(((MessageDeliveryException) payload).getCause())
|
||||
.isInstanceOf(AuthenticationCredentialsNotFoundException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSecurityContextPropagationExecutorChannel() {
|
||||
login("bob", "bobspassword", "ROLE_ADMIN", "ROLE_PRESIDENT");
|
||||
this.executorChannel.send(new GenericMessage<String>("test"));
|
||||
this.executorChannel.send(new GenericMessage<>("test"));
|
||||
Message<?> receive = this.securedChannelQueue.receive(10000);
|
||||
assertThat(receive).isNotNull();
|
||||
|
||||
SecurityContextHolder.clearContext();
|
||||
|
||||
this.executorChannel.send(new GenericMessage<String>("test"));
|
||||
this.executorChannel.send(new GenericMessage<>("test"));
|
||||
Message<?> errorMessage = this.errorChannel.receive(10000);
|
||||
assertThat(errorMessage).isNotNull();
|
||||
Object payload = errorMessage.getPayload();
|
||||
assertThat(payload).isInstanceOf(MessageHandlingException.class);
|
||||
assertThat(((MessageHandlingException) payload).getCause())
|
||||
assertThat(payload).isInstanceOf(MessageDeliveryException.class);
|
||||
assertThat(((MessageDeliveryException) payload).getCause())
|
||||
.isInstanceOf(AuthenticationCredentialsNotFoundException.class);
|
||||
}
|
||||
|
||||
@@ -222,7 +227,7 @@ public class ChannelSecurityInterceptorSecuredChannelAnnotationTests {
|
||||
public void testSecurityContextPropagationPublishSubscribeChannel() {
|
||||
login("bob", "bobspassword", "ROLE_ADMIN", "ROLE_PRESIDENT");
|
||||
|
||||
this.publishSubscribeChannel.send(new GenericMessage<String>("test"));
|
||||
this.publishSubscribeChannel.send(new GenericMessage<>("test"));
|
||||
|
||||
Message<?> receive = this.securedChannelQueue.receive(10000);
|
||||
assertThat(receive).isNotNull();
|
||||
@@ -236,7 +241,7 @@ public class ChannelSecurityInterceptorSecuredChannelAnnotationTests {
|
||||
|
||||
this.publishSubscribeChannel.setApplySequence(true);
|
||||
|
||||
this.publishSubscribeChannel.send(new GenericMessage<String>("test"));
|
||||
this.publishSubscribeChannel.send(new GenericMessage<>("test"));
|
||||
|
||||
receive = this.securedChannelQueue.receive(10000);
|
||||
assertThat(receive).isNotNull();
|
||||
@@ -252,12 +257,12 @@ public class ChannelSecurityInterceptorSecuredChannelAnnotationTests {
|
||||
|
||||
SecurityContextHolder.clearContext();
|
||||
|
||||
this.publishSubscribeChannel.send(new GenericMessage<String>("test"));
|
||||
this.publishSubscribeChannel.send(new GenericMessage<>("test"));
|
||||
Message<?> errorMessage = this.errorChannel.receive(10000);
|
||||
assertThat(errorMessage).isNotNull();
|
||||
Object payload = errorMessage.getPayload();
|
||||
assertThat(payload).isInstanceOf(MessageHandlingException.class);
|
||||
assertThat(((MessageHandlingException) payload).getCause())
|
||||
assertThat(payload).isInstanceOf(MessageDeliveryException.class);
|
||||
assertThat(((MessageDeliveryException) payload).getCause())
|
||||
.isInstanceOf(AuthenticationCredentialsNotFoundException.class);
|
||||
}
|
||||
|
||||
@@ -285,22 +290,38 @@ public class ChannelSecurityInterceptorSecuredChannelAnnotationTests {
|
||||
@Configuration
|
||||
@EnableIntegration
|
||||
@IntegrationComponentScan
|
||||
@ImportResource("classpath:org/springframework/integration/security/config/commonSecurityConfiguration.xml")
|
||||
public static class ContextConfiguration {
|
||||
|
||||
@Bean
|
||||
UserDetailsService userDetailsService() {
|
||||
return new InMemoryUserDetailsManager(
|
||||
User.withUsername("jimi")
|
||||
.password("jimispassword")
|
||||
.authorities("ROLE_USER", "ROLE_ADMIN")
|
||||
.build(),
|
||||
User.withUsername("bob")
|
||||
.password("bobspassword")
|
||||
.authorities("ROLE_USER")
|
||||
.build());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
|
||||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SecuredChannel(interceptor = "channelSecurityInterceptor", sendAccess = {"ROLE_ADMIN", "ROLE_PRESIDENT"})
|
||||
@GlobalChannelInterceptor(patterns = "secured*")
|
||||
AuthorizationChannelInterceptor authorizationChannelInterceptor() {
|
||||
return new AuthorizationChannelInterceptor(AuthorityAuthorizationManager.hasAnyRole("ADMIN", "PRESIDENT"));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SubscribableChannel securedChannel() {
|
||||
return new DirectChannel();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SecuredChannel(interceptor = "channelSecurityInterceptor", sendAccess = {"ROLE_ADMIN", "ROLE_PRESIDENT"})
|
||||
public SubscribableChannel securedChannel2() {
|
||||
return new DirectChannel();
|
||||
}
|
||||
@@ -326,7 +347,6 @@ public class ChannelSecurityInterceptorSecuredChannelAnnotationTests {
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SecuredChannel(interceptor = "channelSecurityInterceptor", sendAccess = {"ROLE_ADMIN", "ROLE_PRESIDENT"})
|
||||
public PollableChannel securedChannelQueue() {
|
||||
return new QueueChannel();
|
||||
}
|
||||
@@ -353,7 +373,6 @@ public class ChannelSecurityInterceptorSecuredChannelAnnotationTests {
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SecuredChannel(interceptor = "channelSecurityInterceptor", sendAccess = {"ROLE_ADMIN", "ROLE_PRESIDENT"})
|
||||
public PollableChannel securedChannelQueue2() {
|
||||
return new QueueChannel();
|
||||
}
|
||||
@@ -386,15 +405,6 @@ public class ChannelSecurityInterceptorSecuredChannelAnnotationTests {
|
||||
return testHandler;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ChannelSecurityInterceptor channelSecurityInterceptor(AuthenticationManager authenticationManager,
|
||||
AccessDecisionManager accessDecisionManager) {
|
||||
ChannelSecurityInterceptor channelSecurityInterceptor = new ChannelSecurityInterceptor();
|
||||
channelSecurityInterceptor.setAuthenticationManager(authenticationManager);
|
||||
channelSecurityInterceptor.setAccessDecisionManager(accessDecisionManager);
|
||||
return channelSecurityInterceptor;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AsyncTaskExecutor securityContextExecutor() {
|
||||
return new DelegatingSecurityContextAsyncTaskExecutor(new SimpleAsyncTaskExecutor());
|
||||
@@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:security="http://www.springframework.org/schema/integration/security"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
https://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration/security
|
||||
https://www.springframework.org/schema/integration/security/spring-integration-security.xsd">
|
||||
|
||||
<import resource="classpath:org/springframework/integration/security/config/commonSecurityConfiguration.xml"/>
|
||||
|
||||
<security:secured-channels>
|
||||
<security:access-policy pattern="test" send-access="ROLE_ADMIN"/>
|
||||
</security:secured-channels>
|
||||
|
||||
</beans>
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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
|
||||
*
|
||||
* https://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.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.integration.channel.MessagePublishingErrorHandler;
|
||||
import org.springframework.integration.channel.NullChannel;
|
||||
import org.springframework.integration.channel.PublishSubscribeChannel;
|
||||
import org.springframework.integration.context.IntegrationContextUtils;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.ErrorHandler;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Artem Bilan
|
||||
* @author Gary Russell
|
||||
* @since 1.0.3
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class DefaultConfigurationTests {
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext context;
|
||||
|
||||
|
||||
@Test
|
||||
public void verifyErrorChannel() {
|
||||
Object errorChannel = context.getBean("errorChannel");
|
||||
assertThat(errorChannel).isNotNull();
|
||||
assertThat(errorChannel.getClass()).isEqualTo(PublishSubscribeChannel.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyNullChannel() {
|
||||
Object nullChannel = context.getBean("nullChannel");
|
||||
assertThat(nullChannel).isNotNull();
|
||||
assertThat(nullChannel.getClass()).isEqualTo(NullChannel.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyTaskScheduler() {
|
||||
Object taskScheduler = context.getBean(IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME);
|
||||
assertThat(taskScheduler.getClass()).isEqualTo(ThreadPoolTaskScheduler.class);
|
||||
ErrorHandler errorHandler = TestUtils.getPropertyValue(taskScheduler, "errorHandler", ErrorHandler.class);
|
||||
assertThat(errorHandler.getClass()).isEqualTo(MessagePublishingErrorHandler.class);
|
||||
MessageChannel defaultErrorChannel = TestUtils.getPropertyValue(errorHandler,
|
||||
"messagingTemplate.defaultDestination", MessageChannel.class);
|
||||
assertThat(defaultErrorChannel).isNull();
|
||||
errorHandler.handleError(new Throwable());
|
||||
defaultErrorChannel = TestUtils.getPropertyValue(errorHandler, "messagingTemplate.defaultDestination",
|
||||
MessageChannel.class);
|
||||
assertThat(defaultErrorChannel).isNotNull();
|
||||
assertThat(defaultErrorChannel).isEqualTo(context.getBean(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/integration"
|
||||
xmlns:si-security="http://www.springframework.org/schema/integration/security"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:security="http://www.springframework.org/schema/security"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
https://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/security
|
||||
https://www.springframework.org/schema/security/spring-security.xsd
|
||||
http://www.springframework.org/schema/integration
|
||||
https://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/integration/security
|
||||
https://www.springframework.org/schema/integration/security/spring-integration-security.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
https://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
<beans:import resource="classpath:org/springframework/integration/security/config/commonSecurityConfiguration.xml"/>
|
||||
|
||||
<si-security:secured-channels>
|
||||
<si-security:access-policy pattern="adminRequiredForSend" send-access="ROLE_ADMIN"/>
|
||||
<si-security:access-policy pattern="adminOrUserRequiredForSend" send-access="ROLE_ADMIN, ROLE_USER"/>
|
||||
<si-security:access-policy pattern="adminRequiredForReceive" receive-access="ROLE_ADMIN"/>
|
||||
<si-security:access-policy pattern="adminOrUserRequiredForReceive" receive-access="ROLE_ADMIN, ROLE_USER"/>
|
||||
<si-security:access-policy pattern="adminRequiredForSendAndReceive" send-access="ROLE_ADMIN" receive-access="ROLE_ADMIN"/>
|
||||
</si-security:secured-channels>
|
||||
|
||||
</beans:beans>
|
||||
@@ -1,216 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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
|
||||
*
|
||||
* https://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.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.integration.channel.AbstractPollableChannel;
|
||||
import org.springframework.integration.core.MessageSelector;
|
||||
import org.springframework.integration.security.channel.ChannelAccessPolicy;
|
||||
import org.springframework.integration.security.channel.ChannelSecurityInterceptor;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.support.ChannelInterceptor;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
|
||||
|
||||
/**
|
||||
* @author Jonas Partner
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
*/
|
||||
@ContextConfiguration
|
||||
public class SecuredChannelsParserTests extends AbstractJUnit4SpringContextTests {
|
||||
|
||||
TestMessageChannel messageChannel;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
messageChannel = new TestMessageChannel();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdminRequiredForSend() {
|
||||
String beanName = "adminRequiredForSend";
|
||||
messageChannel.setBeanName(beanName);
|
||||
MessageChannel proxy = (MessageChannel) applicationContext.getAutowireCapableBeanFactory()
|
||||
.applyBeanPostProcessorsAfterInitialization(messageChannel, beanName);
|
||||
assertThat(AopUtils.isAopProxy(proxy)).as("Channel was not proxied").isTrue();
|
||||
Advisor[] advisors = ((Advised) proxy).getAdvisors();
|
||||
assertThat(advisors.length).as("Wrong number of interceptors").isEqualTo(1);
|
||||
ChannelSecurityInterceptor interceptor = (ChannelSecurityInterceptor) advisors[0].getAdvice();
|
||||
ChannelAccessPolicy policy = this.retrievePolicyForPatternString(beanName, interceptor);
|
||||
assertThat(policy).as("Pattern '" + beanName + "' is not included in mappings").isNotNull();
|
||||
Collection<ConfigAttribute> sendDefinition = policy.getConfigAttributesForSend();
|
||||
Collection<ConfigAttribute> receiveDefinition = policy.getConfigAttributesForReceive();
|
||||
assertThat(this.getRolesFromDefintion(sendDefinition).contains("ROLE_ADMIN"))
|
||||
.as("ROLE_ADMIN not found as send attribute").isTrue();
|
||||
assertThat(receiveDefinition.size() == 0).as("Policy applies to receive").isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdminOrUserRequiredForSend() {
|
||||
String beanName = "adminOrUserRequiredForSend";
|
||||
messageChannel.setBeanName(beanName);
|
||||
MessageChannel proxy = (MessageChannel) applicationContext.getAutowireCapableBeanFactory()
|
||||
.applyBeanPostProcessorsAfterInitialization(messageChannel, beanName);
|
||||
assertThat(AopUtils.isAopProxy(proxy)).as("Channel was not proxied").isTrue();
|
||||
Advisor[] advisors = ((Advised) proxy).getAdvisors();
|
||||
assertThat(advisors.length).as("Wrong number of interceptors").isEqualTo(1);
|
||||
ChannelSecurityInterceptor interceptor = (ChannelSecurityInterceptor) advisors[0].getAdvice();
|
||||
ChannelAccessPolicy policy = this.retrievePolicyForPatternString(beanName, interceptor);
|
||||
assertThat(policy).as("Pattern '" + beanName + "' is not included in mappings").isNotNull();
|
||||
Collection<ConfigAttribute> sendDefinition = policy.getConfigAttributesForSend();
|
||||
Collection<ConfigAttribute> receiveDefinition = policy.getConfigAttributesForReceive();
|
||||
Collection<String> sendRoles = this.getRolesFromDefintion(sendDefinition);
|
||||
assertThat(sendRoles.contains("ROLE_ADMIN")).as("ROLE_ADMIN not found as send attribute").isTrue();
|
||||
assertThat(sendRoles.contains("ROLE_USER")).as("ROLE_USER not found as send attribute").isTrue();
|
||||
assertThat(receiveDefinition.size() == 0).as("Policy applies to receive").isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdminRequiredForReceive() {
|
||||
String beanName = "adminRequiredForReceive";
|
||||
messageChannel.setBeanName(beanName);
|
||||
MessageChannel proxy = (MessageChannel) applicationContext.getAutowireCapableBeanFactory()
|
||||
.applyBeanPostProcessorsAfterInitialization(messageChannel, beanName);
|
||||
assertThat(AopUtils.isAopProxy(proxy)).as("Channel was not proxied").isTrue();
|
||||
Advisor[] advisors = ((Advised) proxy).getAdvisors();
|
||||
assertThat(advisors.length).as("Wrong number of interceptors").isEqualTo(1);
|
||||
ChannelSecurityInterceptor interceptor = (ChannelSecurityInterceptor) advisors[0].getAdvice();
|
||||
ChannelAccessPolicy policy = this.retrievePolicyForPatternString(beanName, interceptor);
|
||||
assertThat(policy).as("Pattern '" + beanName + "' is not included in mappings").isNotNull();
|
||||
Collection<ConfigAttribute> sendDefinition = policy.getConfigAttributesForSend();
|
||||
Collection<ConfigAttribute> receiveDefinition = policy.getConfigAttributesForReceive();
|
||||
Collection<String> receiveRoles = this.getRolesFromDefintion(receiveDefinition);
|
||||
assertThat(receiveRoles.contains("ROLE_ADMIN")).as("ROLE_ADMIN not found as receive attribute").isTrue();
|
||||
assertThat(sendDefinition.size() == 0).as("Policy applies to receive").isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdminOrUserRequiredForReceive() {
|
||||
String beanName = "adminOrUserRequiredForReceive";
|
||||
messageChannel.setBeanName(beanName);
|
||||
MessageChannel proxy = (MessageChannel) applicationContext.getAutowireCapableBeanFactory()
|
||||
.applyBeanPostProcessorsAfterInitialization(messageChannel, beanName);
|
||||
assertThat(AopUtils.isAopProxy(proxy)).as("Channel was not proxied").isTrue();
|
||||
Advisor[] advisors = ((Advised) proxy).getAdvisors();
|
||||
assertThat(advisors.length).as("Wrong number of interceptors").isEqualTo(1);
|
||||
ChannelSecurityInterceptor interceptor = (ChannelSecurityInterceptor) advisors[0].getAdvice();
|
||||
ChannelAccessPolicy policy = this.retrievePolicyForPatternString(beanName, interceptor);
|
||||
assertThat(policy).as("Pattern '" + beanName + "' is not included in mappings").isNotNull();
|
||||
Collection<ConfigAttribute> sendDefinition = policy.getConfigAttributesForSend();
|
||||
Collection<ConfigAttribute> receiveDefinition = policy.getConfigAttributesForReceive();
|
||||
Collection<String> receiveRoles = this.getRolesFromDefintion(receiveDefinition);
|
||||
assertThat(receiveRoles.contains("ROLE_ADMIN")).as("ROLE_ADMIN not found as receive attribute").isTrue();
|
||||
assertThat(receiveRoles.contains("ROLE_USER")).as("ROLE_USER not found as receive attribute").isTrue();
|
||||
assertThat(sendDefinition.size() == 0).as("Policy applies to receive").isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdminRequiredForSendAndReceive() {
|
||||
String beanName = "adminRequiredForSendAndReceive";
|
||||
messageChannel.setBeanName(beanName);
|
||||
MessageChannel proxy = (MessageChannel) applicationContext.getAutowireCapableBeanFactory()
|
||||
.applyBeanPostProcessorsAfterInitialization(messageChannel, beanName);
|
||||
assertThat(AopUtils.isAopProxy(proxy)).as("Channel was not proxied").isTrue();
|
||||
Advisor[] advisors = ((Advised) proxy).getAdvisors();
|
||||
assertThat(advisors.length).as("Wrong number of interceptors").isEqualTo(1);
|
||||
ChannelSecurityInterceptor interceptor = (ChannelSecurityInterceptor) advisors[0].getAdvice();
|
||||
ChannelAccessPolicy policy = this.retrievePolicyForPatternString(beanName, interceptor);
|
||||
assertThat(policy).as("Pattern '" + beanName + "' is not included in mappings").isNotNull();
|
||||
Collection<ConfigAttribute> sendDefinition = policy.getConfigAttributesForSend();
|
||||
Collection<ConfigAttribute> receiveDefinition = policy.getConfigAttributesForReceive();
|
||||
assertThat(sendDefinition).as("Pattern does not apply to 'send'").isNotNull();
|
||||
assertThat(receiveDefinition).as("Pattern does not apply to 'receive'").isNotNull();
|
||||
Collection<String> sendRoles = this.getRolesFromDefintion(sendDefinition);
|
||||
Collection<String> receiveRoles = this.getRolesFromDefintion(receiveDefinition);
|
||||
assertThat(sendRoles.contains("ROLE_ADMIN")).as("ROLE_ADMIN not found in send attributes").isTrue();
|
||||
assertThat(receiveRoles.contains("ROLE_ADMIN")).as("ROLE_ADMIN not found in receive attributes").isTrue();
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private ChannelAccessPolicy retrievePolicyForPatternString(String patternString, ChannelSecurityInterceptor interceptor) {
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(interceptor.obtainSecurityMetadataSource());
|
||||
Map<Pattern, ChannelAccessPolicy> policies = (Map<Pattern, ChannelAccessPolicy>) accessor.getPropertyValue("patternMappings");
|
||||
for (Map.Entry<Pattern, ChannelAccessPolicy> entry : policies.entrySet()) {
|
||||
if (entry.getKey().pattern().equals(patternString)) {
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Collection<String> getRolesFromDefintion(Collection<ConfigAttribute> definition) {
|
||||
Set<String> roles = new HashSet<String>();
|
||||
//Collection configAttributes = SecurityConfig.createListFromCommaDelimitedString(definition);
|
||||
for (ConfigAttribute nextConfigAttribute : definition) {
|
||||
ConfigAttribute attribute = nextConfigAttribute;
|
||||
roles.add(attribute.getAttribute());
|
||||
}
|
||||
return roles;
|
||||
}
|
||||
|
||||
|
||||
static class TestMessageChannel extends AbstractPollableChannel {
|
||||
|
||||
List<ChannelInterceptor> interceptors = new ArrayList<ChannelInterceptor>();
|
||||
|
||||
|
||||
@Override
|
||||
protected Message<?> doReceive(long timeout) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doSend(Message<?> message, long timeout) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<Message<?>> clear() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<Message<?>> purge(MessageSelector selector) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptor(ChannelInterceptor interceptor) {
|
||||
interceptors.add(interceptor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/integration"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:security="http://www.springframework.org/schema/security"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
https://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
https://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
<context:annotation-config/>
|
||||
|
||||
<beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
|
||||
<beans:constructor-arg>
|
||||
<beans:bean class="org.springframework.security.access.vote.RoleVoter"/>
|
||||
</beans:constructor-arg>
|
||||
<beans:property name="allowIfAllAbstainDecisions" value="true"/>
|
||||
</beans:bean>
|
||||
|
||||
<security:authentication-manager alias="authenticationManager">
|
||||
<security:authentication-provider user-service-ref="userDetailsService"/>
|
||||
</security:authentication-manager>
|
||||
|
||||
<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>
|
||||
|
||||
</beans:beans>
|
||||
Reference in New Issue
Block a user