INT-3663: Fix Early BF Access for Security Module
JIRA: https://jira.spring.io/browse/INT-3663 Previously the `ChannelSecurityInterceptorBeanPostProcessor` was populated with direct `BeanDefinition`s for `ChannelSecurityInterceptor`s. It caused an `early access to BeanFactory`. The issue has been introduced by the `ChannelSecurityInterceptorFactoryBean` * Rework `SecurityIntegrationConfigurationInitializer` do not populate `BeanDefinition`s to the `ChannelSecurityInterceptorBeanPostProcessor`, but just `bean names` * Redesign `ChannelSecurityInterceptorBeanPostProcessor` to the `AbstractAutoProxyCreator` * Introduce `SecuredChannel` annotation to be used on the `@Bean` level for `MessageChannel` definition * Move `access policy` mapping to the `SecuredChannel` annotation Address PR comments Document `@SecuredChannel` annotation
This commit is contained in:
committed by
Gary Russell
parent
2653ce9aed
commit
b6cfd4fa76
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.channel;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.security.config.ChannelSecurityInterceptorBeanPostProcessor;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
public class ChannelSecurityInterceptorBeanPostProcessorTests {
|
||||
|
||||
@Test
|
||||
public void securedChannelIsProxied() throws Exception {
|
||||
ChannelSecurityMetadataSource securityMetadataSource = new ChannelSecurityMetadataSource();
|
||||
securityMetadataSource.addPatternMapping(Pattern.compile("secured.*"),
|
||||
new DefaultChannelAccessPolicy("ROLE_ADMIN", null));
|
||||
|
||||
ChannelSecurityInterceptor interceptor = new ChannelSecurityInterceptor(securityMetadataSource);
|
||||
|
||||
ChannelSecurityInterceptorBeanPostProcessor postProcessor =
|
||||
new ChannelSecurityInterceptorBeanPostProcessor(Arrays.asList(interceptor));
|
||||
|
||||
QueueChannel securedChannel = new QueueChannel();
|
||||
securedChannel.setBeanName("securedChannel");
|
||||
MessageChannel postProcessedChannel =
|
||||
(MessageChannel) postProcessor.postProcessAfterInitialization(securedChannel, "securedChannel");
|
||||
assertTrue(AopUtils.isAopProxy(postProcessedChannel));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonsecuredChannelIsNotProxied() throws Exception {
|
||||
ChannelSecurityMetadataSource securityMetadataSource = new ChannelSecurityMetadataSource();
|
||||
securityMetadataSource.addPatternMapping(Pattern.compile("secured.*"),
|
||||
new DefaultChannelAccessPolicy("ROLE_ADMIN", null));
|
||||
|
||||
ChannelSecurityInterceptor interceptor = new ChannelSecurityInterceptor(securityMetadataSource);
|
||||
|
||||
ChannelSecurityInterceptorBeanPostProcessor postProcessor =
|
||||
new ChannelSecurityInterceptorBeanPostProcessor(Arrays.asList(interceptor));
|
||||
|
||||
QueueChannel channel = new QueueChannel();
|
||||
channel.setBeanName("testChannel");
|
||||
MessageChannel postProcessedChannel =
|
||||
(MessageChannel) postProcessor.postProcessAfterInitialization(channel, "testChannel");
|
||||
assertFalse(AopUtils.isAopProxy(postProcessedChannel));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2015 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.
|
||||
@@ -30,10 +30,14 @@ import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.config.EnableIntegration;
|
||||
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.messaging.MessageChannel;
|
||||
import org.springframework.messaging.SubscribableChannel;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.security.access.AccessDecisionManager;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
@@ -48,7 +52,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
|
||||
public class ChannelSecurityInterceptorFactoryBeanTests {
|
||||
public class ChannelSecurityInterceptorSecuredChannelAnnotationTests {
|
||||
|
||||
@Autowired
|
||||
MessageChannel securedChannel;
|
||||
@@ -133,11 +137,13 @@ public class ChannelSecurityInterceptorFactoryBeanTests {
|
||||
public static class ContextConfiguration {
|
||||
|
||||
@Bean
|
||||
@SecuredChannel(interceptor = "channelSecurityInterceptor", sendAccess = {"ROLE_ADMIN", "ROLE_PRESIDENT"})
|
||||
public SubscribableChannel securedChannel() {
|
||||
return new DirectChannel();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SecuredChannel(interceptor = "channelSecurityInterceptor", sendAccess = {"ROLE_ADMIN", "ROLE_PRESIDENT"})
|
||||
public SubscribableChannel securedChannel2() {
|
||||
return new DirectChannel();
|
||||
}
|
||||
@@ -157,9 +163,12 @@ public class ChannelSecurityInterceptorFactoryBeanTests {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ChannelSecurityInterceptorFactoryBean channelSecurityInterceptor() {
|
||||
return new ChannelSecurityInterceptorFactoryBean()
|
||||
.accessPolicy("securedChannel.*", "ROLE_ADMIN, ROLE_PRESIDENT");
|
||||
public ChannelSecurityInterceptor channelSecurityInterceptor(AuthenticationManager authenticationManager,
|
||||
AccessDecisionManager accessDecisionManager) {
|
||||
ChannelSecurityInterceptor channelSecurityInterceptor = new ChannelSecurityInterceptor();
|
||||
channelSecurityInterceptor.setAuthenticationManager(authenticationManager);
|
||||
channelSecurityInterceptor.setAccessDecisionManager(accessDecisionManager);
|
||||
return channelSecurityInterceptor;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user