15 changed files with 292 additions and 49 deletions
@ -0,0 +1,81 @@
@@ -0,0 +1,81 @@
|
||||
package org.springframework.security.config; |
||||
|
||||
import static org.junit.Assert.fail; |
||||
|
||||
import org.junit.After; |
||||
import org.junit.AfterClass; |
||||
import org.junit.Before; |
||||
import org.junit.BeforeClass; |
||||
import org.junit.Test; |
||||
import org.springframework.context.support.ClassPathXmlApplicationContext; |
||||
import org.springframework.security.AccessDeniedException; |
||||
import org.springframework.security.AuthenticationCredentialsNotFoundException; |
||||
import org.springframework.security.GrantedAuthority; |
||||
import org.springframework.security.GrantedAuthorityImpl; |
||||
import org.springframework.security.annotation.BusinessService; |
||||
import org.springframework.security.context.SecurityContextHolder; |
||||
import org.springframework.security.providers.UsernamePasswordAuthenticationToken; |
||||
|
||||
/** |
||||
* @author Ben Alex |
||||
* @version $Id: InterceptMethodsBeanDefinitionDecoratorTests.java 2217 2007-10-27 00:45:30Z luke_t $ |
||||
*/ |
||||
public class AnnotatedMethodSecurityBeanDefinitionDecoratorTests { |
||||
private static ClassPathXmlApplicationContext appContext; |
||||
|
||||
private BusinessService target; |
||||
|
||||
@BeforeClass |
||||
public static void loadContext() { |
||||
appContext = new ClassPathXmlApplicationContext("org/springframework/security/config/annotated-method-security.xml"); |
||||
} |
||||
|
||||
@AfterClass |
||||
public static void closeAppContext() { |
||||
if (appContext != null) { |
||||
appContext.close(); |
||||
} |
||||
} |
||||
|
||||
@Before |
||||
public void setUp() { |
||||
target = (BusinessService) appContext.getBean("target"); |
||||
} |
||||
|
||||
@After |
||||
public void clearSecurityContext() { |
||||
SecurityContextHolder.clearContext(); |
||||
} |
||||
|
||||
@Test |
||||
public void targetShouldPreventProtectedMethodInvocationWithNoContext() { |
||||
try { |
||||
target.someUserMethod1(); |
||||
fail("Expected AuthenticationCredentialsNotFoundException"); |
||||
} catch (AuthenticationCredentialsNotFoundException expected) { |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void targetShouldAllowProtectedMethodInvocationWithCorrectRole() { |
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", |
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_USER")}); |
||||
SecurityContextHolder.getContext().setAuthentication(token); |
||||
|
||||
|
||||
target.someUserMethod1(); |
||||
} |
||||
|
||||
@Test |
||||
public void targetShouldPreventProtectedMethodInvocationWithIncorrectRole() { |
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", |
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_SOMEOTHERROLE")}); |
||||
SecurityContextHolder.getContext().setAuthentication(token); |
||||
|
||||
try { |
||||
target.someAdminMethod(); |
||||
fail("Expected AccessDeniedException"); |
||||
} catch (AccessDeniedException expected) { |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
||||
<b:beans xmlns="http://www.springframework.org/schema/security" |
||||
xmlns:b="http://www.springframework.org/schema/beans" |
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd |
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd"> |
||||
|
||||
<b:bean id="target" class="org.springframework.security.annotation.BusinessServiceImpl"/> |
||||
|
||||
<annotation-driven/> |
||||
|
||||
<repository> |
||||
<user-service> |
||||
<user name="bob" password="bobspassword" authorities="ROLE_A,ROLE_B" /> |
||||
<user name="bill" password="billspassword" authorities="ROLE_A,ROLE_B,AUTH_OTHER" /> |
||||
</user-service> |
||||
</repository> |
||||
|
||||
</b:beans> |
||||
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
package org.springframework.security.config; |
||||
|
||||
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; |
||||
import org.springframework.beans.factory.config.BeanDefinition; |
||||
import org.springframework.beans.factory.config.RuntimeBeanReference; |
||||
import org.springframework.beans.factory.support.RootBeanDefinition; |
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser; |
||||
import org.springframework.beans.factory.xml.ParserContext; |
||||
import org.springframework.metadata.Attributes; |
||||
import org.springframework.security.intercept.method.MethodDefinitionAttributes; |
||||
import org.springframework.security.intercept.method.aopalliance.MethodDefinitionSourceAdvisor; |
||||
import org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor; |
||||
import org.springframework.util.Assert; |
||||
import org.springframework.util.ClassUtils; |
||||
import org.springframework.util.ReflectionUtils; |
||||
import org.w3c.dom.Element; |
||||
|
||||
/** |
||||
* Processes the top-level "annotation-driven" element. |
||||
* |
||||
* @author Ben Alex |
||||
* @version $Id$ |
||||
*/ |
||||
class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { |
||||
|
||||
public static final String SECURITY_ANNOTATION_ATTRIBUTES_CLASS = "org.springframework.security.annotation.SecurityAnnotationAttributes"; |
||||
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) { |
||||
// Reflectively obtain the Annotation-based ObjectDefinitionSource.
|
||||
// Reflection is used to avoid a compile-time dependency on SECURITY_ANNOTATION_ATTRIBUTES_CLASS, as this parser is in the Java 4 project whereas the dependency is in the Tiger project.
|
||||
Assert.isTrue(ClassUtils.isPresent(SECURITY_ANNOTATION_ATTRIBUTES_CLASS), "Could not locate class '" + SECURITY_ANNOTATION_ATTRIBUTES_CLASS + "' - please ensure the spring-security-tiger-xxx.jar is in your classpath and you are running Java 5 or above."); |
||||
Class clazz = null; |
||||
try { |
||||
clazz = ClassUtils.forName(SECURITY_ANNOTATION_ATTRIBUTES_CLASS); |
||||
} catch (Exception ex) { |
||||
ReflectionUtils.handleReflectionException(ex); |
||||
} |
||||
|
||||
RootBeanDefinition securityAnnotations = new RootBeanDefinition(clazz); |
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.SECURITY_ANNOTATION_ATTRIBUTES, securityAnnotations); |
||||
|
||||
RootBeanDefinition methodDefinitionAttributes = new RootBeanDefinition(MethodDefinitionAttributes.class); |
||||
methodDefinitionAttributes.getPropertyValues().addPropertyValue("attributes", new RuntimeBeanReference(BeanIds.SECURITY_ANNOTATION_ATTRIBUTES)); |
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.METHOD_DEFINITION_ATTRIBUTES, methodDefinitionAttributes); |
||||
|
||||
MethodSecurityInterceptorUtils.registerPostProcessorIfNecessary(parserContext.getRegistry()); |
||||
|
||||
RootBeanDefinition interceptor = new RootBeanDefinition(MethodSecurityInterceptor.class); |
||||
interceptor.getPropertyValues().addPropertyValue("objectDefinitionSource", new RuntimeBeanReference(BeanIds.METHOD_DEFINITION_ATTRIBUTES)); |
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.METHOD_SECURITY_INTERCEPTOR, interceptor); |
||||
|
||||
RootBeanDefinition advisor = new RootBeanDefinition(MethodDefinitionSourceAdvisor.class); |
||||
advisor.getConstructorArgumentValues().addGenericArgumentValue(interceptor); |
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.METHOD_DEFINITION_SOURCE_ADVISOR, advisor); |
||||
|
||||
RootBeanDefinition daapc = new RootBeanDefinition(DefaultAdvisorAutoProxyCreator.class); |
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.DEFAULT_ADVISOR_AUTO_PROXY_CREATOR, daapc); |
||||
|
||||
|
||||
return null; |
||||
} |
||||
} |
||||
@ -0,0 +1,53 @@
@@ -0,0 +1,53 @@
|
||||
package org.springframework.security.config; |
||||
|
||||
import org.springframework.beans.BeansException; |
||||
import org.springframework.beans.factory.config.BeanDefinition; |
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor; |
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; |
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry; |
||||
import org.springframework.beans.factory.support.RootBeanDefinition; |
||||
import org.springframework.core.Ordered; |
||||
import org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor; |
||||
|
||||
/** |
||||
* Provides convenience methods supporting method security configuration. |
||||
* |
||||
* @author Ben Alex |
||||
* @author Luke Taylor |
||||
* |
||||
*/ |
||||
abstract class MethodSecurityInterceptorUtils { |
||||
|
||||
private static class MethodSecurityConfigPostProcessor implements BeanFactoryPostProcessor, Ordered { |
||||
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { |
||||
String[] interceptors = beanFactory.getBeanNamesForType(MethodSecurityInterceptor.class); |
||||
|
||||
for (int i=0; i < interceptors.length; i++) { |
||||
BeanDefinition interceptor = beanFactory.getBeanDefinition(interceptors[i]); |
||||
ConfigUtils.configureSecurityInterceptor(beanFactory, interceptor); |
||||
} |
||||
} |
||||
|
||||
public int getOrder() { |
||||
return HIGHEST_PRECEDENCE; |
||||
} |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Causes a BeanFactoryPostProcessor to be registered that will ensure all MethodSecurityInterceptor |
||||
* instances are properly configured with an AccessDecisionManager etc. |
||||
* |
||||
* @param registry to register the BeanPostProcessorWith |
||||
*/ |
||||
public static void registerPostProcessorIfNecessary(BeanDefinitionRegistry registry) { |
||||
if (registry.containsBeanDefinition(BeanIds.INTERCEPT_METHODS_BEAN_FACTORY_POST_PROCESSOR)) { |
||||
return; |
||||
} |
||||
|
||||
registry.registerBeanDefinition(BeanIds.INTERCEPT_METHODS_BEAN_FACTORY_POST_PROCESSOR, |
||||
new RootBeanDefinition(MethodSecurityInterceptorUtils.MethodSecurityConfigPostProcessor.class)); |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue