mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-28 14:52:24 +00:00
SEC-999: First commit of expression-based authorization implementation
This commit is contained in:
parent
0dd82cb91a
commit
4aa32f7d06
11
core/pom.xml
11
core/pom.xml
@ -10,6 +10,11 @@
|
|||||||
<name>Spring Security - Core</name>
|
<name>Spring Security - Core</name>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security</groupId>
|
||||||
|
<artifactId>spring-el-security</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-core</artifactId>
|
<artifactId>spring-core</artifactId>
|
||||||
@ -39,13 +44,11 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.aspectj</groupId>
|
<groupId>org.aspectj</groupId>
|
||||||
<artifactId>aspectjrt</artifactId>
|
<artifactId>com.springsource.org.aspectj.runtime</artifactId>
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.aspectj</groupId>
|
<groupId>org.aspectj</groupId>
|
||||||
<artifactId>aspectjweaver</artifactId>
|
<artifactId>com.springsource.org.aspectj.weaver</artifactId>
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.ldap</groupId>
|
<groupId>org.springframework.ldap</groupId>
|
||||||
|
@ -99,33 +99,6 @@ public class ConfigAttributeDefinition implements Serializable {
|
|||||||
this.configAttributes = Collections.unmodifiableList(new ArrayList(configAttributes));
|
this.configAttributes = Collections.unmodifiableList(new ArrayList(configAttributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a <tt>ConfigAttributeDefinition</tt> by including only those attributes which implement <tt>ConfigAttribute</tt>.
|
|
||||||
*
|
|
||||||
* @param unfilteredInput a collection of various elements, zero or more which implement <tt>ConfigAttribute</tt> (can also be <tt>null</tt>)
|
|
||||||
* @return a ConfigAttributeDefinition if at least one <tt>ConfigAttribute</tt> was present, or <tt>null</tt> if none implemented it
|
|
||||||
*/
|
|
||||||
public static ConfigAttributeDefinition createFiltered(Collection unfilteredInput) {
|
|
||||||
if (unfilteredInput == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
List configAttributes = new ArrayList();
|
|
||||||
Iterator i = unfilteredInput.iterator();
|
|
||||||
while (i.hasNext()) {
|
|
||||||
Object element = i.next();
|
|
||||||
if (element instanceof ConfigAttribute) {
|
|
||||||
configAttributes.add(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configAttributes.size() == 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ConfigAttributeDefinition(configAttributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
//~ Methods ========================================================================================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -160,7 +133,7 @@ public class ConfigAttributeDefinition implements Serializable {
|
|||||||
*
|
*
|
||||||
* @return the configuration attributes stored in this instance.
|
* @return the configuration attributes stored in this instance.
|
||||||
*/
|
*/
|
||||||
public Collection getConfigAttributes() {
|
public Collection<ConfigAttribute> getConfigAttributes() {
|
||||||
return this.configAttributes;
|
return this.configAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,8 +36,7 @@ import java.util.Set;
|
|||||||
class ArrayFilterer implements Filterer {
|
class ArrayFilterer implements Filterer {
|
||||||
//~ Static fields/initializers =====================================================================================
|
//~ Static fields/initializers =====================================================================================
|
||||||
|
|
||||||
protected static final Log logger =
|
protected static final Log logger = LogFactory.getLog(ArrayFilterer.class);
|
||||||
LogFactory.getLog(BasicAclEntryAfterInvocationCollectionFilteringProvider.class);
|
|
||||||
|
|
||||||
//~ Instance fields ================================================================================================
|
//~ Instance fields ================================================================================================
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ import java.util.Iterator;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter strategy interface.
|
* Filterer strategy interface.
|
||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
* @author Paulo Neves
|
* @author Paulo Neves
|
||||||
|
@ -26,6 +26,7 @@ import javax.annotation.security.PermitAll;
|
|||||||
import javax.annotation.security.RolesAllowed;
|
import javax.annotation.security.RolesAllowed;
|
||||||
|
|
||||||
import org.springframework.core.annotation.AnnotationUtils;
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
|
import org.springframework.security.ConfigAttribute;
|
||||||
import org.springframework.security.ConfigAttributeDefinition;
|
import org.springframework.security.ConfigAttributeDefinition;
|
||||||
import org.springframework.security.intercept.method.AbstractFallbackMethodDefinitionSource;
|
import org.springframework.security.intercept.method.AbstractFallbackMethodDefinitionSource;
|
||||||
|
|
||||||
@ -39,38 +40,42 @@ import org.springframework.security.intercept.method.AbstractFallbackMethodDefin
|
|||||||
*/
|
*/
|
||||||
public class Jsr250MethodDefinitionSource extends AbstractFallbackMethodDefinitionSource {
|
public class Jsr250MethodDefinitionSource extends AbstractFallbackMethodDefinitionSource {
|
||||||
|
|
||||||
protected ConfigAttributeDefinition findAttributes(Class clazz) {
|
protected List<ConfigAttribute> findAttributes(Class clazz) {
|
||||||
return processAnnotations(clazz.getAnnotations());
|
return processAnnotations(clazz.getAnnotations());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ConfigAttributeDefinition findAttributes(Method method, Class targetClass) {
|
protected List<ConfigAttribute> findAttributes(Method method, Class targetClass) {
|
||||||
return processAnnotations(AnnotationUtils.getAnnotations(method));
|
return processAnnotations(AnnotationUtils.getAnnotations(method));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getConfigAttributeDefinitions() {
|
public Collection getConfigAttributeDefinitions() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConfigAttributeDefinition processAnnotations(Annotation[] annotations) {
|
private List<ConfigAttribute> processAnnotations(Annotation[] annotations) {
|
||||||
if (annotations == null || annotations.length == 0) {
|
if (annotations == null || annotations.length == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
for (Annotation a: annotations) {
|
List<ConfigAttribute> attributes = new ArrayList<ConfigAttribute>();
|
||||||
if (a instanceof DenyAll) {
|
|
||||||
return new ConfigAttributeDefinition(Jsr250SecurityConfig.DENY_ALL_ATTRIBUTE);
|
for (Annotation a: annotations) {
|
||||||
}
|
if (a instanceof DenyAll) {
|
||||||
if (a instanceof PermitAll) {
|
attributes.add(Jsr250SecurityConfig.DENY_ALL_ATTRIBUTE);
|
||||||
return new ConfigAttributeDefinition(Jsr250SecurityConfig.PERMIT_ALL_ATTRIBUTE);
|
return attributes;
|
||||||
}
|
}
|
||||||
if (a instanceof RolesAllowed) {
|
if (a instanceof PermitAll) {
|
||||||
RolesAllowed ra = (RolesAllowed) a;
|
attributes.add(Jsr250SecurityConfig.PERMIT_ALL_ATTRIBUTE);
|
||||||
List attributes = new ArrayList();
|
return attributes;
|
||||||
for (String allowed : ra.value()) {
|
}
|
||||||
attributes.add(new Jsr250SecurityConfig(allowed));
|
if (a instanceof RolesAllowed) {
|
||||||
}
|
RolesAllowed ra = (RolesAllowed) a;
|
||||||
return new ConfigAttributeDefinition(attributes);
|
|
||||||
}
|
for (String allowed : ra.value()) {
|
||||||
}
|
attributes.add(new Jsr250SecurityConfig(allowed));
|
||||||
return null;
|
}
|
||||||
}
|
return attributes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,13 @@ package org.springframework.security.annotation;
|
|||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.core.annotation.AnnotationUtils;
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
import org.springframework.security.ConfigAttributeDefinition;
|
import org.springframework.security.ConfigAttribute;
|
||||||
|
import org.springframework.security.SecurityConfig;
|
||||||
import org.springframework.security.intercept.method.AbstractFallbackMethodDefinitionSource;
|
import org.springframework.security.intercept.method.AbstractFallbackMethodDefinitionSource;
|
||||||
|
|
||||||
|
|
||||||
@ -32,23 +35,30 @@ import org.springframework.security.intercept.method.AbstractFallbackMethodDefin
|
|||||||
*/
|
*/
|
||||||
public class SecuredMethodDefinitionSource extends AbstractFallbackMethodDefinitionSource {
|
public class SecuredMethodDefinitionSource extends AbstractFallbackMethodDefinitionSource {
|
||||||
|
|
||||||
protected ConfigAttributeDefinition findAttributes(Class clazz) {
|
protected List<ConfigAttribute> findAttributes(Class clazz) {
|
||||||
return processAnnotation(clazz.getAnnotation(Secured.class));
|
return processAnnotation(clazz.getAnnotation(Secured.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ConfigAttributeDefinition findAttributes(Method method, Class targetClass) {
|
protected List<ConfigAttribute> findAttributes(Method method, Class targetClass) {
|
||||||
return processAnnotation(AnnotationUtils.findAnnotation(method, Secured.class));
|
return processAnnotation(AnnotationUtils.findAnnotation(method, Secured.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getConfigAttributeDefinitions() {
|
public Collection getConfigAttributeDefinitions() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConfigAttributeDefinition processAnnotation(Annotation a) {
|
private List<ConfigAttribute> processAnnotation(Annotation a) {
|
||||||
if (a == null || !(a instanceof Secured)) {
|
if (a == null || !(a instanceof Secured)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Secured secured = (Secured) a;
|
|
||||||
return new ConfigAttributeDefinition(secured.value());
|
String[] attributeTokens = ((Secured) a).value();
|
||||||
}
|
List<ConfigAttribute> attributes = new ArrayList<ConfigAttribute>(attributeTokens.length);
|
||||||
|
|
||||||
|
for(String token : attributeTokens) {
|
||||||
|
attributes.add(new SecurityConfig(token));
|
||||||
|
}
|
||||||
|
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ public abstract class BeanIds {
|
|||||||
public static final String SPRING_SECURITY_FILTER_CHAIN = "springSecurityFilterChain";
|
public static final String SPRING_SECURITY_FILTER_CHAIN = "springSecurityFilterChain";
|
||||||
|
|
||||||
/** Package protected as end users shouldn't really be using this BFPP directly */
|
/** Package protected as end users shouldn't really be using this BFPP directly */
|
||||||
static final String INTERCEPT_METHODS_BEAN_FACTORY_POST_PROCESSOR = "_interceptMethodsBeanfactoryPP";
|
static final String INTERCEPT_METHODS_BEAN_FACTORY_POST_PROCESSOR = "_interceptMethodsBeanfactoryPP";
|
||||||
static final String CONTEXT_SOURCE_SETTING_POST_PROCESSOR = "_contextSettingPostProcessor";
|
static final String CONTEXT_SOURCE_SETTING_POST_PROCESSOR = "_contextSettingPostProcessor";
|
||||||
static final String ENTRY_POINT_INJECTION_POST_PROCESSOR = "_entryPointInjectionBeanPostProcessor";
|
static final String ENTRY_POINT_INJECTION_POST_PROCESSOR = "_entryPointInjectionBeanPostProcessor";
|
||||||
static final String USER_DETAILS_SERVICE_INJECTION_POST_PROCESSOR = "_userServiceInjectionPostProcessor";
|
static final String USER_DETAILS_SERVICE_INJECTION_POST_PROCESSOR = "_userServiceInjectionPostProcessor";
|
||||||
@ -23,44 +23,45 @@ public abstract class BeanIds {
|
|||||||
static final String FILTER_LIST = "_filterChainList";
|
static final String FILTER_LIST = "_filterChainList";
|
||||||
|
|
||||||
public static final String JDBC_USER_DETAILS_MANAGER = "_jdbcUserDetailsManager";
|
public static final String JDBC_USER_DETAILS_MANAGER = "_jdbcUserDetailsManager";
|
||||||
public static final String USER_DETAILS_SERVICE = "_userDetailsService";
|
public static final String USER_DETAILS_SERVICE = "_userDetailsService";
|
||||||
public static final String ANONYMOUS_PROCESSING_FILTER = "_anonymousProcessingFilter";
|
public static final String ANONYMOUS_PROCESSING_FILTER = "_anonymousProcessingFilter";
|
||||||
public static final String ANONYMOUS_AUTHENTICATION_PROVIDER = "_anonymousAuthenticationProvider";
|
public static final String ANONYMOUS_AUTHENTICATION_PROVIDER = "_anonymousAuthenticationProvider";
|
||||||
public static final String BASIC_AUTHENTICATION_FILTER = "_basicAuthenticationFilter";
|
public static final String BASIC_AUTHENTICATION_FILTER = "_basicAuthenticationFilter";
|
||||||
public static final String BASIC_AUTHENTICATION_ENTRY_POINT = "_basicAuthenticationEntryPoint";
|
public static final String BASIC_AUTHENTICATION_ENTRY_POINT = "_basicAuthenticationEntryPoint";
|
||||||
public static final String SESSION_REGISTRY = "_sessionRegistry";
|
public static final String SESSION_REGISTRY = "_sessionRegistry";
|
||||||
public static final String CONCURRENT_SESSION_FILTER = "_concurrentSessionFilter";
|
public static final String CONCURRENT_SESSION_FILTER = "_concurrentSessionFilter";
|
||||||
public static final String CONCURRENT_SESSION_CONTROLLER = "_concurrentSessionController";
|
public static final String CONCURRENT_SESSION_CONTROLLER = "_concurrentSessionController";
|
||||||
public static final String ACCESS_MANAGER = "_accessManager";
|
public static final String METHOD_ACCESS_MANAGER = "_methodAccessManager";
|
||||||
public static final String AUTHENTICATION_MANAGER = "_authenticationManager";
|
public static final String WEB_ACCESS_MANAGER = "_webAccessManager";
|
||||||
public static final String AFTER_INVOCATION_MANAGER = "_afterInvocationManager";
|
public static final String AUTHENTICATION_MANAGER = "_authenticationManager";
|
||||||
public static final String FORM_LOGIN_FILTER = "_formLoginFilter";
|
public static final String AFTER_INVOCATION_MANAGER = "_afterInvocationManager";
|
||||||
public static final String FORM_LOGIN_ENTRY_POINT = "_formLoginEntryPoint";
|
public static final String FORM_LOGIN_FILTER = "_formLoginFilter";
|
||||||
public static final String OPEN_ID_FILTER = "_openIDFilter";
|
public static final String FORM_LOGIN_ENTRY_POINT = "_formLoginEntryPoint";
|
||||||
public static final String OPEN_ID_ENTRY_POINT = "_openIDFilterEntryPoint";
|
public static final String OPEN_ID_FILTER = "_openIDFilter";
|
||||||
|
public static final String OPEN_ID_ENTRY_POINT = "_openIDFilterEntryPoint";
|
||||||
public static final String OPEN_ID_PROVIDER = "_openIDAuthenticationProvider";
|
public static final String OPEN_ID_PROVIDER = "_openIDAuthenticationProvider";
|
||||||
public static final String MAIN_ENTRY_POINT = "_mainEntryPoint";
|
public static final String MAIN_ENTRY_POINT = "_mainEntryPoint";
|
||||||
public static final String FILTER_CHAIN_PROXY = "_filterChainProxy";
|
public static final String FILTER_CHAIN_PROXY = "_filterChainProxy";
|
||||||
public static final String HTTP_SESSION_CONTEXT_INTEGRATION_FILTER = "_httpSessionContextIntegrationFilter";
|
public static final String HTTP_SESSION_CONTEXT_INTEGRATION_FILTER = "_httpSessionContextIntegrationFilter";
|
||||||
public static final String LDAP_AUTHENTICATION_PROVIDER = "_ldapAuthenticationProvider";
|
public static final String LDAP_AUTHENTICATION_PROVIDER = "_ldapAuthenticationProvider";
|
||||||
public static final String LOGOUT_FILTER = "_logoutFilter";
|
public static final String LOGOUT_FILTER = "_logoutFilter";
|
||||||
public static final String EXCEPTION_TRANSLATION_FILTER = "_exceptionTranslationFilter";
|
public static final String EXCEPTION_TRANSLATION_FILTER = "_exceptionTranslationFilter";
|
||||||
public static final String FILTER_SECURITY_INTERCEPTOR = "_filterSecurityInterceptor";
|
public static final String FILTER_SECURITY_INTERCEPTOR = "_filterSecurityInterceptor";
|
||||||
public static final String CHANNEL_PROCESSING_FILTER = "_channelProcessingFilter";
|
public static final String CHANNEL_PROCESSING_FILTER = "_channelProcessingFilter";
|
||||||
public static final String CHANNEL_DECISION_MANAGER = "_channelDecisionManager";
|
public static final String CHANNEL_DECISION_MANAGER = "_channelDecisionManager";
|
||||||
public static final String REMEMBER_ME_FILTER = "_rememberMeFilter";
|
public static final String REMEMBER_ME_FILTER = "_rememberMeFilter";
|
||||||
public static final String REMEMBER_ME_SERVICES = "_rememberMeServices";
|
public static final String REMEMBER_ME_SERVICES = "_rememberMeServices";
|
||||||
public static final String REMEMBER_ME_AUTHENTICATION_PROVIDER = "_rememberMeAuthenticationProvider";
|
public static final String REMEMBER_ME_AUTHENTICATION_PROVIDER = "_rememberMeAuthenticationProvider";
|
||||||
public static final String DEFAULT_LOGIN_PAGE_GENERATING_FILTER = "_defaultLoginPageFilter";
|
public static final String DEFAULT_LOGIN_PAGE_GENERATING_FILTER = "_defaultLoginPageFilter";
|
||||||
public static final String SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER = "_securityContextHolderAwareRequestFilter";
|
public static final String SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER = "_securityContextHolderAwareRequestFilter";
|
||||||
public static final String SESSION_FIXATION_PROTECTION_FILTER = "_sessionFixationProtectionFilter";
|
public static final String SESSION_FIXATION_PROTECTION_FILTER = "_sessionFixationProtectionFilter";
|
||||||
public static final String METHOD_SECURITY_INTERCEPTOR = "_methodSecurityInterceptor";
|
public static final String METHOD_SECURITY_INTERCEPTOR = "_methodSecurityInterceptor";
|
||||||
public static final String METHOD_SECURITY_INTERCEPTOR_POST_PROCESSOR = "_methodSecurityInterceptorPostProcessor";
|
public static final String METHOD_SECURITY_INTERCEPTOR_POST_PROCESSOR = "_methodSecurityInterceptorPostProcessor";
|
||||||
public static final String METHOD_DEFINITION_SOURCE_ADVISOR = "_methodDefinitionSourceAdvisor";
|
public static final String METHOD_DEFINITION_SOURCE_ADVISOR = "_methodDefinitionSourceAdvisor";
|
||||||
public static final String PROTECT_POINTCUT_POST_PROCESSOR = "_protectPointcutPostProcessor";
|
public static final String PROTECT_POINTCUT_POST_PROCESSOR = "_protectPointcutPostProcessor";
|
||||||
public static final String DELEGATING_METHOD_DEFINITION_SOURCE = "_delegatingMethodDefinitionSource";
|
public static final String DELEGATING_METHOD_DEFINITION_SOURCE = "_delegatingMethodDefinitionSource";
|
||||||
public static final String SECURED_METHOD_DEFINITION_SOURCE = "_securedMethodDefinitionSource";
|
public static final String SECURED_METHOD_DEFINITION_SOURCE = "_securedMethodDefinitionSource";
|
||||||
public static final String JSR_250_METHOD_DEFINITION_SOURCE = "_jsr250MethodDefinitionSource";
|
public static final String JSR_250_METHOD_DEFINITION_SOURCE = "_jsr250MethodDefinitionSource";
|
||||||
public static final String EMBEDDED_APACHE_DS = "_apacheDirectoryServerContainer";
|
public static final String EMBEDDED_APACHE_DS = "_apacheDirectoryServerContainer";
|
||||||
public static final String CONTEXT_SOURCE = "_securityContextSource";
|
public static final String CONTEXT_SOURCE = "_securityContextSource";
|
||||||
public static final String PORT_MAPPER = "_portMapper";
|
public static final String PORT_MAPPER = "_portMapper";
|
||||||
|
@ -3,8 +3,6 @@ package org.springframework.security.config;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.springframework.beans.BeanMetadataElement;
|
import org.springframework.beans.BeanMetadataElement;
|
||||||
import org.springframework.beans.MutablePropertyValues;
|
import org.springframework.beans.MutablePropertyValues;
|
||||||
import org.springframework.beans.PropertyValue;
|
import org.springframework.beans.PropertyValue;
|
||||||
@ -15,6 +13,7 @@ import org.springframework.beans.factory.support.ManagedList;
|
|||||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||||
import org.springframework.beans.factory.xml.ParserContext;
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
import org.springframework.security.afterinvocation.AfterInvocationProviderManager;
|
import org.springframework.security.afterinvocation.AfterInvocationProviderManager;
|
||||||
|
import org.springframework.security.expression.support.MethodExpressionVoter;
|
||||||
import org.springframework.security.util.UrlUtils;
|
import org.springframework.security.util.UrlUtils;
|
||||||
import org.springframework.security.vote.AffirmativeBased;
|
import org.springframework.security.vote.AffirmativeBased;
|
||||||
import org.springframework.security.vote.AuthenticatedVoter;
|
import org.springframework.security.vote.AuthenticatedVoter;
|
||||||
@ -29,41 +28,50 @@ import org.w3c.dom.Element;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public abstract class ConfigUtils {
|
abstract class ConfigUtils {
|
||||||
private static final Log logger = LogFactory.getLog(ConfigUtils.class);
|
|
||||||
|
|
||||||
static void registerDefaultAccessManagerIfNecessary(ParserContext parserContext) {
|
static void registerDefaultWebAccessManagerIfNecessary(ParserContext parserContext) {
|
||||||
|
if (!parserContext.getRegistry().containsBeanDefinition(BeanIds.WEB_ACCESS_MANAGER)) {
|
||||||
if (!parserContext.getRegistry().containsBeanDefinition(BeanIds.ACCESS_MANAGER)) {
|
parserContext.getRegistry().registerBeanDefinition(BeanIds.WEB_ACCESS_MANAGER,
|
||||||
ManagedList defaultVoters = new ManagedList(2);
|
createAccessManagerBean(RoleVoter.class, AuthenticatedVoter.class));
|
||||||
|
|
||||||
defaultVoters.add(new RootBeanDefinition(RoleVoter.class));
|
|
||||||
defaultVoters.add(new RootBeanDefinition(AuthenticatedVoter.class));
|
|
||||||
|
|
||||||
BeanDefinitionBuilder accessMgrBuilder = BeanDefinitionBuilder.rootBeanDefinition(AffirmativeBased.class);
|
|
||||||
accessMgrBuilder.addPropertyValue("decisionVoters", defaultVoters);
|
|
||||||
BeanDefinition accessMgr = accessMgrBuilder.getBeanDefinition();
|
|
||||||
|
|
||||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.ACCESS_MANAGER, accessMgr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int countNonEmpty(String[] objects) {
|
static void registerDefaultMethodAccessManagerIfNecessary(ParserContext parserContext) {
|
||||||
int nonNulls = 0;
|
if (!parserContext.getRegistry().containsBeanDefinition(BeanIds.METHOD_ACCESS_MANAGER)) {
|
||||||
|
parserContext.getRegistry().registerBeanDefinition(BeanIds.METHOD_ACCESS_MANAGER,
|
||||||
for (int i = 0; i < objects.length; i++) {
|
createAccessManagerBean(MethodExpressionVoter.class, RoleVoter.class, AuthenticatedVoter.class));
|
||||||
if (StringUtils.hasText(objects[i])) {
|
}
|
||||||
nonNulls++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nonNulls;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addVoter(BeanDefinition voter, ParserContext parserContext) {
|
private static BeanDefinition createAccessManagerBean(Class... voters) {
|
||||||
registerDefaultAccessManagerIfNecessary(parserContext);
|
ManagedList defaultVoters = new ManagedList(voters.length);
|
||||||
|
|
||||||
BeanDefinition accessMgr = parserContext.getRegistry().getBeanDefinition(BeanIds.ACCESS_MANAGER);
|
for(Class voter : voters) {
|
||||||
|
defaultVoters.add(new RootBeanDefinition(voter));
|
||||||
|
}
|
||||||
|
|
||||||
|
BeanDefinitionBuilder accessMgrBuilder = BeanDefinitionBuilder.rootBeanDefinition(AffirmativeBased.class);
|
||||||
|
accessMgrBuilder.addPropertyValue("decisionVoters", defaultVoters);
|
||||||
|
return accessMgrBuilder.getBeanDefinition();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int countNonEmpty(String[] objects) {
|
||||||
|
int nonNulls = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < objects.length; i++) {
|
||||||
|
if (StringUtils.hasText(objects[i])) {
|
||||||
|
nonNulls++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nonNulls;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addVoter(BeanDefinition voter, ParserContext parserContext) {
|
||||||
|
registerDefaultMethodAccessManagerIfNecessary(parserContext);
|
||||||
|
|
||||||
|
BeanDefinition accessMgr = parserContext.getRegistry().getBeanDefinition(BeanIds.METHOD_ACCESS_MANAGER);
|
||||||
|
|
||||||
ManagedList voters = (ManagedList) accessMgr.getPropertyValues().getPropertyValue("decisionVoters").getValue();
|
ManagedList voters = (ManagedList) accessMgr.getPropertyValues().getPropertyValue("decisionVoters").getValue();
|
||||||
voters.add(voter);
|
voters.add(voter);
|
||||||
@ -93,10 +101,10 @@ public abstract class ConfigUtils {
|
|||||||
((ArrayList) authManager.getPropertyValues().getPropertyValue("providerBeanNames").getValue()).add(beanName);
|
((ArrayList) authManager.getPropertyValues().getPropertyValue("providerBeanNames").getValue()).add(beanName);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ManagedList getRegisteredAfterInvocationProviders(ParserContext parserContext) {
|
static ManagedList getRegisteredAfterInvocationProviders(ParserContext parserContext) {
|
||||||
BeanDefinition manager = registerAfterInvocationProviderManagerIfNecessary(parserContext);
|
BeanDefinition manager = registerAfterInvocationProviderManagerIfNecessary(parserContext);
|
||||||
return (ManagedList) manager.getPropertyValues().getPropertyValue("providers").getValue();
|
return (ManagedList) manager.getPropertyValues().getPropertyValue("providers").getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BeanDefinition registerAfterInvocationProviderManagerIfNecessary(ParserContext parserContext) {
|
private static BeanDefinition registerAfterInvocationProviderManagerIfNecessary(ParserContext parserContext) {
|
||||||
if(parserContext.getRegistry().containsBeanDefinition(BeanIds.AFTER_INVOCATION_MANAGER)) {
|
if(parserContext.getRegistry().containsBeanDefinition(BeanIds.AFTER_INVOCATION_MANAGER)) {
|
||||||
@ -108,12 +116,12 @@ public abstract class ConfigUtils {
|
|||||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.AFTER_INVOCATION_MANAGER, manager);
|
parserContext.getRegistry().registerBeanDefinition(BeanIds.AFTER_INVOCATION_MANAGER, manager);
|
||||||
|
|
||||||
return manager;
|
return manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void registerFilterChainPostProcessorIfNecessary(ParserContext pc) {
|
private static void registerFilterChainPostProcessorIfNecessary(ParserContext pc) {
|
||||||
if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_POST_PROCESSOR)) {
|
if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_POST_PROCESSOR)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Post processor specifically to assemble and order the filter chain immediately before the FilterChainProxy is initialized.
|
// Post processor specifically to assemble and order the filter chain immediately before the FilterChainProxy is initialized.
|
||||||
RootBeanDefinition filterChainPostProcessor = new RootBeanDefinition(FilterChainProxyPostProcessor.class);
|
RootBeanDefinition filterChainPostProcessor = new RootBeanDefinition(FilterChainProxyPostProcessor.class);
|
||||||
filterChainPostProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
filterChainPostProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||||
@ -124,20 +132,20 @@ public abstract class ConfigUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void addHttpFilter(ParserContext pc, BeanMetadataElement filter) {
|
static void addHttpFilter(ParserContext pc, BeanMetadataElement filter) {
|
||||||
registerFilterChainPostProcessorIfNecessary(pc);
|
registerFilterChainPostProcessorIfNecessary(pc);
|
||||||
|
|
||||||
RootBeanDefinition filterList = (RootBeanDefinition) pc.getRegistry().getBeanDefinition(BeanIds.FILTER_LIST);
|
RootBeanDefinition filterList = (RootBeanDefinition) pc.getRegistry().getBeanDefinition(BeanIds.FILTER_LIST);
|
||||||
|
|
||||||
ManagedList filters;
|
ManagedList filters;
|
||||||
MutablePropertyValues pvs = filterList.getPropertyValues();
|
MutablePropertyValues pvs = filterList.getPropertyValues();
|
||||||
if (pvs.contains("filters")) {
|
if (pvs.contains("filters")) {
|
||||||
filters = (ManagedList) pvs.getPropertyValue("filters").getValue();
|
filters = (ManagedList) pvs.getPropertyValue("filters").getValue();
|
||||||
} else {
|
} else {
|
||||||
filters = new ManagedList();
|
filters = new ManagedList();
|
||||||
pvs.addPropertyValue("filters", filters);
|
pvs.addPropertyValue("filters", filters);
|
||||||
}
|
}
|
||||||
|
|
||||||
filters.add(filter);
|
filters.add(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -145,15 +153,15 @@ public abstract class ConfigUtils {
|
|||||||
* addHttpFilter. The post processor retrieves these before injecting the list into the FilterChainProxy.
|
* addHttpFilter. The post processor retrieves these before injecting the list into the FilterChainProxy.
|
||||||
*/
|
*/
|
||||||
public static class FilterChainList {
|
public static class FilterChainList {
|
||||||
List filters;
|
List filters;
|
||||||
|
|
||||||
public List getFilters() {
|
public List getFilters() {
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFilters(List filters) {
|
public void setFilters(List filters) {
|
||||||
this.filters = filters;
|
this.filters = filters;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -161,21 +169,21 @@ public abstract class ConfigUtils {
|
|||||||
* If not empty or starting with "$" (potential placeholder), "/" or "http" it will raise an error.
|
* If not empty or starting with "$" (potential placeholder), "/" or "http" it will raise an error.
|
||||||
*/
|
*/
|
||||||
static void validateHttpRedirect(String url, ParserContext pc, Object source) {
|
static void validateHttpRedirect(String url, ParserContext pc, Object source) {
|
||||||
if (UrlUtils.isValidRedirectUrl(url) || url.startsWith("$")) {
|
if (UrlUtils.isValidRedirectUrl(url) || url.startsWith("$")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pc.getReaderContext().warning(url + " is not a valid redirect URL (must start with '/' or http(s))", source);
|
pc.getReaderContext().warning(url + " is not a valid redirect URL (must start with '/' or http(s))", source);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setSessionControllerOnAuthenticationManager(ParserContext pc, String beanName, Element sourceElt) {
|
static void setSessionControllerOnAuthenticationManager(ParserContext pc, String beanName, Element sourceElt) {
|
||||||
registerProviderManagerIfNecessary(pc);
|
registerProviderManagerIfNecessary(pc);
|
||||||
BeanDefinition authManager = pc.getRegistry().getBeanDefinition(BeanIds.AUTHENTICATION_MANAGER);
|
BeanDefinition authManager = pc.getRegistry().getBeanDefinition(BeanIds.AUTHENTICATION_MANAGER);
|
||||||
PropertyValue pv = authManager.getPropertyValues().getPropertyValue("sessionController");
|
PropertyValue pv = authManager.getPropertyValues().getPropertyValue("sessionController");
|
||||||
|
|
||||||
if (pv != null && pv.getValue() != null) {
|
if (pv != null && pv.getValue() != null) {
|
||||||
pc.getReaderContext().error("A session controller has already been set on the authentication manager. " +
|
pc.getReaderContext().error("A session controller has already been set on the authentication manager. " +
|
||||||
"The <concurrent-session-control> element isn't compatible with a custom session controller",
|
"The <concurrent-session-control> element isn't compatible with a custom session controller",
|
||||||
pc.extractSource(sourceElt));
|
pc.extractSource(sourceElt));
|
||||||
}
|
}
|
||||||
|
|
||||||
authManager.getPropertyValues().addPropertyValue("sessionController", new RuntimeBeanReference(beanName));
|
authManager.getPropertyValues().addPropertyValue("sessionController", new RuntimeBeanReference(beanName));
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.springframework.security.config;
|
package org.springframework.security.config;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -14,7 +15,9 @@ import org.springframework.beans.factory.support.ManagedList;
|
|||||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||||
import org.springframework.beans.factory.xml.ParserContext;
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
import org.springframework.security.ConfigAttributeDefinition;
|
import org.springframework.security.ConfigAttribute;
|
||||||
|
import org.springframework.security.SecurityConfig;
|
||||||
|
import org.springframework.security.expression.support.MethodExpressionAfterInvocationProvider;
|
||||||
import org.springframework.security.intercept.method.DelegatingMethodDefinitionSource;
|
import org.springframework.security.intercept.method.DelegatingMethodDefinitionSource;
|
||||||
import org.springframework.security.intercept.method.MapBasedMethodDefinitionSource;
|
import org.springframework.security.intercept.method.MapBasedMethodDefinitionSource;
|
||||||
import org.springframework.security.intercept.method.ProtectPointcutPostProcessor;
|
import org.springframework.security.intercept.method.ProtectPointcutPostProcessor;
|
||||||
@ -33,6 +36,7 @@ import org.w3c.dom.Element;
|
|||||||
class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||||
public static final String SECURED_DEPENDENCY_CLASS = "org.springframework.security.annotation.Secured";
|
public static final String SECURED_DEPENDENCY_CLASS = "org.springframework.security.annotation.Secured";
|
||||||
public static final String SECURED_METHOD_DEFINITION_SOURCE_CLASS = "org.springframework.security.annotation.SecuredMethodDefinitionSource";
|
public static final String SECURED_METHOD_DEFINITION_SOURCE_CLASS = "org.springframework.security.annotation.SecuredMethodDefinitionSource";
|
||||||
|
public static final String EXPRESSION_METHOD_DEFINITION_SOURCE_CLASS = "org.springframework.security.expression.support.ExpressionAnnotationMethodDefinitionSource";
|
||||||
public static final String JSR_250_SECURITY_METHOD_DEFINITION_SOURCE_CLASS = "org.springframework.security.annotation.Jsr250MethodDefinitionSource";
|
public static final String JSR_250_SECURITY_METHOD_DEFINITION_SOURCE_CLASS = "org.springframework.security.annotation.Jsr250MethodDefinitionSource";
|
||||||
public static final String JSR_250_VOTER_CLASS = "org.springframework.security.annotation.Jsr250Voter";
|
public static final String JSR_250_VOTER_CLASS = "org.springframework.security.annotation.Jsr250Voter";
|
||||||
private static final String ATT_ACCESS = "access";
|
private static final String ATT_ACCESS = "access";
|
||||||
@ -40,6 +44,7 @@ class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
private static final String ATT_ACCESS_MGR = "access-decision-manager-ref";
|
private static final String ATT_ACCESS_MGR = "access-decision-manager-ref";
|
||||||
private static final String ATT_USE_JSR250 = "jsr250-annotations";
|
private static final String ATT_USE_JSR250 = "jsr250-annotations";
|
||||||
private static final String ATT_USE_SECURED = "secured-annotations";
|
private static final String ATT_USE_SECURED = "secured-annotations";
|
||||||
|
private static final String ATT_USE_EXPRESSIONS = "spel-annotations";
|
||||||
|
|
||||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||||
Object source = parserContext.extractSource(element);
|
Object source = parserContext.extractSource(element);
|
||||||
@ -61,17 +66,21 @@ class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
|
|
||||||
registerDelegatingMethodDefinitionSource(parserContext, delegates, source);
|
registerDelegatingMethodDefinitionSource(parserContext, delegates, source);
|
||||||
|
|
||||||
|
// Add the expression-based after invocation provider
|
||||||
|
ConfigUtils.getRegisteredAfterInvocationProviders(parserContext).add(
|
||||||
|
new RootBeanDefinition(MethodExpressionAfterInvocationProvider.class));
|
||||||
|
|
||||||
// Register the applicable AccessDecisionManager, handling the special JSR 250 voter if being used
|
// Register the applicable AccessDecisionManager, handling the special JSR 250 voter if being used
|
||||||
String accessManagerId = element.getAttribute(ATT_ACCESS_MGR);
|
String accessManagerId = element.getAttribute(ATT_ACCESS_MGR);
|
||||||
|
|
||||||
if (!StringUtils.hasText(accessManagerId)) {
|
if (!StringUtils.hasText(accessManagerId)) {
|
||||||
ConfigUtils.registerDefaultAccessManagerIfNecessary(parserContext);
|
ConfigUtils.registerDefaultMethodAccessManagerIfNecessary(parserContext);
|
||||||
|
|
||||||
if (jsr250Enabled) {
|
if (jsr250Enabled) {
|
||||||
ConfigUtils.addVoter(new RootBeanDefinition(JSR_250_VOTER_CLASS, null, null), parserContext);
|
ConfigUtils.addVoter(new RootBeanDefinition(JSR_250_VOTER_CLASS, null, null), parserContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
accessManagerId = BeanIds.ACCESS_MANAGER;
|
accessManagerId = BeanIds.METHOD_ACCESS_MANAGER;
|
||||||
}
|
}
|
||||||
|
|
||||||
registerMethodSecurityInterceptor(parserContext, accessManagerId, source);
|
registerMethodSecurityInterceptor(parserContext, accessManagerId, source);
|
||||||
@ -84,12 +93,17 @@ class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether JSR-250 and/or Secured annotations are enabled and adds the appropriate
|
* Checks whether el-based, JSR-250 and/or Secured annotations are enabled and adds the appropriate
|
||||||
* MethodDefinitionSource delegates if required.
|
* MethodDefinitionSource delegates if required.
|
||||||
*/
|
*/
|
||||||
private boolean registerAnnotationBasedMethodDefinitionSources(Element element, ParserContext pc, ManagedList delegates) {
|
private boolean registerAnnotationBasedMethodDefinitionSources(Element element, ParserContext pc, ManagedList delegates) {
|
||||||
boolean useJsr250 = "enabled".equals(element.getAttribute(ATT_USE_JSR250));
|
boolean useJsr250 = "enabled".equals(element.getAttribute(ATT_USE_JSR250));
|
||||||
boolean useSecured = "enabled".equals(element.getAttribute(ATT_USE_SECURED));
|
boolean useSecured = "enabled".equals(element.getAttribute(ATT_USE_SECURED));
|
||||||
|
boolean useExpressions = "enabled".equals(element.getAttribute(ATT_USE_EXPRESSIONS));
|
||||||
|
|
||||||
|
if (useExpressions) {
|
||||||
|
delegates.add(BeanDefinitionBuilder.rootBeanDefinition(EXPRESSION_METHOD_DEFINITION_SOURCE_CLASS).getBeanDefinition());
|
||||||
|
}
|
||||||
|
|
||||||
if (useSecured) {
|
if (useSecured) {
|
||||||
delegates.add(BeanDefinitionBuilder.rootBeanDefinition(SECURED_METHOD_DEFINITION_SOURCE_CLASS).getBeanDefinition());
|
delegates.add(BeanDefinitionBuilder.rootBeanDefinition(SECURED_METHOD_DEFINITION_SOURCE_CLASS).getBeanDefinition());
|
||||||
@ -139,8 +153,14 @@ class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
parserContext.getReaderContext().error("Pointcut expression required", parserContext.extractSource(childElt));
|
parserContext.getReaderContext().error("Pointcut expression required", parserContext.extractSource(childElt));
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigAttributeDefinition def = new ConfigAttributeDefinition(StringUtils.commaDelimitedListToStringArray(accessConfig));
|
String[] attributeTokens = StringUtils.commaDelimitedListToStringArray(accessConfig);
|
||||||
pointcutMap.put(expression, def);
|
List<ConfigAttribute> attributes = new ArrayList<ConfigAttribute>(attributeTokens.length);
|
||||||
|
|
||||||
|
for(String token : attributeTokens) {
|
||||||
|
attributes.add(new SecurityConfig(token));
|
||||||
|
}
|
||||||
|
|
||||||
|
pointcutMap.put(expression, attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pointcutMap;
|
return pointcutMap;
|
||||||
@ -158,7 +178,7 @@ class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
parserContext.registerComponent(new BeanComponentDefinition(interceptor, BeanIds.METHOD_SECURITY_INTERCEPTOR));
|
parserContext.registerComponent(new BeanComponentDefinition(interceptor, BeanIds.METHOD_SECURITY_INTERCEPTOR));
|
||||||
|
|
||||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.METHOD_SECURITY_INTERCEPTOR_POST_PROCESSOR,
|
parserContext.getRegistry().registerBeanDefinition(BeanIds.METHOD_SECURITY_INTERCEPTOR_POST_PROCESSOR,
|
||||||
new RootBeanDefinition(MethodSecurityInterceptorPostProcessor.class));
|
new RootBeanDefinition(MethodSecurityInterceptorPostProcessor.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerAdvisor(ParserContext parserContext, Object source) {
|
private void registerAdvisor(ParserContext parserContext, Object source) {
|
||||||
|
@ -124,8 +124,8 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
String accessManagerId = element.getAttribute(ATT_ACCESS_MGR);
|
String accessManagerId = element.getAttribute(ATT_ACCESS_MGR);
|
||||||
|
|
||||||
if (!StringUtils.hasText(accessManagerId)) {
|
if (!StringUtils.hasText(accessManagerId)) {
|
||||||
ConfigUtils.registerDefaultAccessManagerIfNecessary(parserContext);
|
ConfigUtils.registerDefaultWebAccessManagerIfNecessary(parserContext);
|
||||||
accessManagerId = BeanIds.ACCESS_MANAGER;
|
accessManagerId = BeanIds.WEB_ACCESS_MANAGER;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register the portMapper. A default will always be created, even if no element exists.
|
// Register the portMapper. A default will always be created, even if no element exists.
|
||||||
@ -273,8 +273,8 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
exceptionTranslationFilterBuilder.addPropertyValue("createSessionAllowed", new Boolean(allowSessionCreation));
|
exceptionTranslationFilterBuilder.addPropertyValue("createSessionAllowed", new Boolean(allowSessionCreation));
|
||||||
|
|
||||||
if (StringUtils.hasText(accessDeniedPage)) {
|
if (StringUtils.hasText(accessDeniedPage)) {
|
||||||
BeanDefinition accessDeniedHandler = new RootBeanDefinition(AccessDeniedHandlerImpl.class);
|
BeanDefinition accessDeniedHandler = new RootBeanDefinition(AccessDeniedHandlerImpl.class);
|
||||||
accessDeniedHandler.getPropertyValues().addPropertyValue("errorPage", accessDeniedPage);
|
accessDeniedHandler.getPropertyValues().addPropertyValue("errorPage", accessDeniedPage);
|
||||||
exceptionTranslationFilterBuilder.addPropertyValue("accessDeniedHandler", accessDeniedHandler);
|
exceptionTranslationFilterBuilder.addPropertyValue("accessDeniedHandler", accessDeniedHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ public class InterceptMethodsBeanDefinitionDecorator implements BeanDefinitionDe
|
|||||||
|
|
||||||
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
|
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
|
||||||
ConfigUtils.registerProviderManagerIfNecessary(parserContext);
|
ConfigUtils.registerProviderManagerIfNecessary(parserContext);
|
||||||
ConfigUtils.registerDefaultAccessManagerIfNecessary(parserContext);
|
ConfigUtils.registerDefaultMethodAccessManagerIfNecessary(parserContext);
|
||||||
|
|
||||||
return delegate.decorate(node, definition, parserContext);
|
return delegate.decorate(node, definition, parserContext);
|
||||||
}
|
}
|
||||||
@ -41,8 +41,8 @@ public class InterceptMethodsBeanDefinitionDecorator implements BeanDefinitionDe
|
|||||||
* registration.
|
* registration.
|
||||||
*/
|
*/
|
||||||
class InternalInterceptMethodsBeanDefinitionDecorator extends AbstractInterceptorDrivenBeanDefinitionDecorator {
|
class InternalInterceptMethodsBeanDefinitionDecorator extends AbstractInterceptorDrivenBeanDefinitionDecorator {
|
||||||
static final String ATT_METHOD = "method";
|
static final String ATT_METHOD = "method";
|
||||||
static final String ATT_ACCESS = "access";
|
static final String ATT_ACCESS = "access";
|
||||||
private static final String ATT_ACCESS_MGR = "access-decision-manager-ref";
|
private static final String ATT_ACCESS_MGR = "access-decision-manager-ref";
|
||||||
|
|
||||||
private Log logger = LogFactory.getLog(getClass());
|
private Log logger = LogFactory.getLog(getClass());
|
||||||
@ -57,16 +57,16 @@ class InternalInterceptMethodsBeanDefinitionDecorator extends AbstractIntercepto
|
|||||||
String accessManagerId = interceptMethodsElt.getAttribute(ATT_ACCESS_MGR);
|
String accessManagerId = interceptMethodsElt.getAttribute(ATT_ACCESS_MGR);
|
||||||
|
|
||||||
if (!StringUtils.hasText(accessManagerId)) {
|
if (!StringUtils.hasText(accessManagerId)) {
|
||||||
accessManagerId = BeanIds.ACCESS_MANAGER;
|
accessManagerId = BeanIds.METHOD_ACCESS_MANAGER;
|
||||||
}
|
}
|
||||||
|
|
||||||
interceptor.addPropertyValue("accessDecisionManager", new RuntimeBeanReference(accessManagerId));
|
interceptor.addPropertyValue("accessDecisionManager", new RuntimeBeanReference(accessManagerId));
|
||||||
interceptor.addPropertyValue("authenticationManager", new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER));
|
interceptor.addPropertyValue("authenticationManager", new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER));
|
||||||
|
|
||||||
// Lookup parent bean information
|
// Lookup parent bean information
|
||||||
Element parent = (Element) node.getParentNode();
|
Element parent = (Element) node.getParentNode();
|
||||||
String parentBeanClass = parent.getAttribute("class");
|
String parentBeanClass = parent.getAttribute("class");
|
||||||
String parentBeanId = parent.getAttribute("id");
|
String parentBeanId = parent.getAttribute("id");
|
||||||
parent = null;
|
parent = null;
|
||||||
|
|
||||||
// Parse the included methods
|
// Parse the included methods
|
||||||
@ -82,9 +82,9 @@ class InternalInterceptMethodsBeanDefinitionDecorator extends AbstractIntercepto
|
|||||||
String methodName = protectmethodElt.getAttribute(ATT_METHOD);
|
String methodName = protectmethodElt.getAttribute(ATT_METHOD);
|
||||||
|
|
||||||
if (methodName.lastIndexOf(".") == -1) {
|
if (methodName.lastIndexOf(".") == -1) {
|
||||||
if (parentBeanClass != null && !"".equals(parentBeanClass)) {
|
if (parentBeanClass != null && !"".equals(parentBeanClass)) {
|
||||||
methodName = parentBeanClass + "." + methodName;
|
methodName = parentBeanClass + "." + methodName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rely on the default property editor for MethodSecurityInterceptor.setObjectDefinitionSource to setup the MethodDefinitionSource
|
// Rely on the default property editor for MethodSecurityInterceptor.setObjectDefinitionSource to setup the MethodDefinitionSource
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
package org.springframework.security.expression;
|
||||||
|
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.springframework.expression.EvaluationException;
|
||||||
|
import org.springframework.expression.Expression;
|
||||||
|
import org.springframework.expression.spel.standard.StandardEvaluationContext;
|
||||||
|
|
||||||
|
public class ExpressionUtils {
|
||||||
|
public static Object doFilter(Object filterTarget, Expression filterExpression, StandardEvaluationContext ctx) {
|
||||||
|
SecurityExpressionRoot rootObject = (SecurityExpressionRoot) ctx.getRootContextObject();
|
||||||
|
Set removeList = new HashSet();
|
||||||
|
|
||||||
|
if (filterTarget instanceof Collection) {
|
||||||
|
for (Object filterObject : (Collection)filterTarget) {
|
||||||
|
rootObject.setFilterObject(filterObject);
|
||||||
|
|
||||||
|
if (!evaluateAsBoolean(filterExpression, ctx)) {
|
||||||
|
removeList.add(filterObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Object toRemove : removeList) {
|
||||||
|
((Collection)filterTarget).remove(toRemove);
|
||||||
|
}
|
||||||
|
|
||||||
|
return filterTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filterTarget.getClass().isArray()) {
|
||||||
|
Object[] array = (Object[])filterTarget;
|
||||||
|
|
||||||
|
for (int i = 0; i < array.length; i++) {
|
||||||
|
rootObject.setFilterObject(array[i]);
|
||||||
|
|
||||||
|
if (!evaluateAsBoolean(filterExpression, ctx)) {
|
||||||
|
removeList.add(array[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object[] filtered = (Object[]) Array.newInstance(filterTarget.getClass().getComponentType(),
|
||||||
|
array.length - removeList.size());
|
||||||
|
for (int i = 0, j = 0; i < array.length; i++) {
|
||||||
|
if (!removeList.contains(array[i])) {
|
||||||
|
filtered[j++] = array[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filtered;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalArgumentException("Filter target must be a collection or array type, but was " + filterTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean evaluateAsBoolean(Expression expr, StandardEvaluationContext ctx) {
|
||||||
|
try {
|
||||||
|
return ((Boolean) expr.getValue(ctx, Boolean.class)).booleanValue();
|
||||||
|
} catch (EvaluationException e) {
|
||||||
|
throw new IllegalArgumentException("Failed to evaluate expression", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package org.springframework.security.expression;
|
||||||
|
|
||||||
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
|
import org.springframework.security.Authentication;
|
||||||
|
|
||||||
|
public class MethodInvocationSecurityExpressionRoot extends SecurityExpressionRoot {
|
||||||
|
|
||||||
|
MethodInvocationSecurityExpressionRoot(Authentication a, MethodInvocation mi) {
|
||||||
|
super(a);
|
||||||
|
|
||||||
|
mi.getArguments();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
package org.springframework.security.expression;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.springframework.security.Authentication;
|
||||||
|
import org.springframework.security.AuthenticationTrustResolver;
|
||||||
|
import org.springframework.security.AuthenticationTrustResolverImpl;
|
||||||
|
import org.springframework.security.util.AuthorityUtils;
|
||||||
|
|
||||||
|
public class SecurityExpressionRoot {
|
||||||
|
private Authentication authentication;
|
||||||
|
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
|
||||||
|
private Object filterObject;
|
||||||
|
private Object returnObject;
|
||||||
|
|
||||||
|
public SecurityExpressionRoot(Authentication a) {
|
||||||
|
this.authentication = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasRole(String role) {
|
||||||
|
return hasAnyRole(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasAnyRole(String... roles) {
|
||||||
|
Set roleSet = AuthorityUtils.authorityArrayToSet(authentication.getAuthorities());
|
||||||
|
|
||||||
|
for (String role : roles) {
|
||||||
|
if (roleSet.contains(role)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAnonymous() {
|
||||||
|
return trustResolver.isAnonymous(authentication);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRememberMe() {
|
||||||
|
return trustResolver.isRememberMe(authentication);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return authentication.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFullyAuthenticated() {
|
||||||
|
return !trustResolver.isAnonymous(authentication) && !trustResolver.isRememberMe(authentication);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilterObject(Object filterObject) {
|
||||||
|
this.filterObject = filterObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getFilterObject() {
|
||||||
|
return filterObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReturnObject(Object returnObject) {
|
||||||
|
this.returnObject = returnObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getReturnObject() {
|
||||||
|
return returnObject;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package org.springframework.security.expression.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Inherited;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation for specifying a method access-control expression which will be evaluated after a method has been invoked.
|
||||||
|
*
|
||||||
|
* @author Luke Taylor
|
||||||
|
* @version $Id$
|
||||||
|
* @since 2.5
|
||||||
|
*/
|
||||||
|
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Inherited
|
||||||
|
@Documented
|
||||||
|
public @interface PostAuthorize {
|
||||||
|
/**
|
||||||
|
* @return the Spring-EL expression to be evaluated after invoking the protected method
|
||||||
|
*/
|
||||||
|
public String value();
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package org.springframework.security.expression.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Inherited;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation for specifying a method filtering expression which will be evaluated after a method has been invoked.
|
||||||
|
*
|
||||||
|
* @author Luke Taylor
|
||||||
|
* @version $Id$
|
||||||
|
* @since 2.5
|
||||||
|
*/
|
||||||
|
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Inherited
|
||||||
|
@Documented
|
||||||
|
public @interface PostFilter {
|
||||||
|
/**
|
||||||
|
* @return the Spring-EL expression to be evaluated after invoking the protected method
|
||||||
|
*/
|
||||||
|
public String value();
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package org.springframework.security.expression.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Inherited;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation for specifying a method access-control expression which will be evaluated to decide whether a
|
||||||
|
* method invocation is allowed or not.
|
||||||
|
*
|
||||||
|
* @author Luke Taylor
|
||||||
|
* @version $Id$
|
||||||
|
* @since 2.5
|
||||||
|
*/
|
||||||
|
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Inherited
|
||||||
|
@Documented
|
||||||
|
public @interface PreAuthorize {
|
||||||
|
/**
|
||||||
|
* @return the Spring-EL expression to be evaluated before invoking the protected method
|
||||||
|
*/
|
||||||
|
String value();
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package org.springframework.security.expression.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Inherited;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation for specifying a method filtering expression which will be evaluated after a method has been invoked.
|
||||||
|
*
|
||||||
|
* @author Luke Taylor
|
||||||
|
* @version $Id$
|
||||||
|
* @since 2.5
|
||||||
|
*/
|
||||||
|
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Inherited
|
||||||
|
@Documented
|
||||||
|
public @interface PreFilter {
|
||||||
|
/**
|
||||||
|
* @return the Spring-EL expression to be evaluated before invoking the protected method
|
||||||
|
*/
|
||||||
|
public String value();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the name of the parameter which should be filtered (must be an array or collection)
|
||||||
|
*/
|
||||||
|
public String filterTarget();
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package org.springframework.security.expression.support;
|
||||||
|
|
||||||
|
import org.springframework.expression.Expression;
|
||||||
|
import org.springframework.expression.ParseException;
|
||||||
|
import org.springframework.expression.spel.SpelExpressionParser;
|
||||||
|
import org.springframework.security.ConfigAttribute;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains both filtering and authorization expression meta-data for Spring-EL based access control.
|
||||||
|
* <p>
|
||||||
|
* Base class for pre or post-invocation phases of a method invocation.
|
||||||
|
* <p>
|
||||||
|
* Either filter or authorization expressions may be null, but not both.
|
||||||
|
*
|
||||||
|
* @author Luke Taylor
|
||||||
|
* @version $Id$
|
||||||
|
* @since 2.5
|
||||||
|
*/
|
||||||
|
abstract class AbstractExpressionBasedMethodConfigAttribute implements ConfigAttribute {
|
||||||
|
private final Expression filterExpression;
|
||||||
|
private final Expression authorizeExpression;
|
||||||
|
|
||||||
|
AbstractExpressionBasedMethodConfigAttribute(String filterExpression, String authorizeExpression) throws ParseException {
|
||||||
|
Assert.isTrue(filterExpression != null || authorizeExpression != null, "Filter and authorization Expressions cannot both be null");
|
||||||
|
SpelExpressionParser parser = new SpelExpressionParser();
|
||||||
|
this.filterExpression = filterExpression == null ? null : parser.parseExpression(filterExpression);
|
||||||
|
this.authorizeExpression = authorizeExpression == null ? null : parser.parseExpression(authorizeExpression);
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression getFilterExpression() {
|
||||||
|
return filterExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression getAuthorizeExpression() {
|
||||||
|
return authorizeExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAttribute() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,111 @@
|
|||||||
|
package org.springframework.security.expression.support;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
|
import org.springframework.expression.ParseException;
|
||||||
|
import org.springframework.security.ConfigAttribute;
|
||||||
|
import org.springframework.security.ConfigAttributeDefinition;
|
||||||
|
import org.springframework.security.config.SecurityConfigurationException;
|
||||||
|
import org.springframework.security.expression.annotation.PostAuthorize;
|
||||||
|
import org.springframework.security.expression.annotation.PostFilter;
|
||||||
|
import org.springframework.security.expression.annotation.PreAuthorize;
|
||||||
|
import org.springframework.security.expression.annotation.PreFilter;
|
||||||
|
import org.springframework.security.intercept.method.AbstractFallbackMethodDefinitionSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MethodDefinitionSource which extracts metadata from the @PreFilter and @PreAuthorize annotations
|
||||||
|
* placed on a method. The metadata is encapsulated in a {@link AbstractExpressionBasedMethodConfigAttribute} instance.
|
||||||
|
*
|
||||||
|
* @see MethodExpressionVoter
|
||||||
|
*
|
||||||
|
* @author Luke Taylor
|
||||||
|
* @since 2.5
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class ExpressionAnnotationMethodDefinitionSource extends AbstractFallbackMethodDefinitionSource {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<ConfigAttribute> findAttributes(Method method, Class targetClass) {
|
||||||
|
ConfigAttribute pre = processPreInvocationAnnotations(AnnotationUtils.findAnnotation(method, PreFilter.class),
|
||||||
|
AnnotationUtils.findAnnotation(method, PreAuthorize.class));
|
||||||
|
ConfigAttribute post = processPostInvocationAnnotations(AnnotationUtils.findAnnotation(method, PostFilter.class),
|
||||||
|
AnnotationUtils.findAnnotation(method, PostAuthorize.class));
|
||||||
|
|
||||||
|
if (pre == null && post == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ConfigAttribute> attrs = new ArrayList<ConfigAttribute>(2);
|
||||||
|
if (pre != null) {
|
||||||
|
attrs.add(pre);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (post != null) {
|
||||||
|
attrs.add(post);
|
||||||
|
}
|
||||||
|
|
||||||
|
return attrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<ConfigAttribute> findAttributes(Class targetClass) {
|
||||||
|
ConfigAttribute pre = processPreInvocationAnnotations((PreFilter)targetClass.getAnnotation(PreFilter.class),
|
||||||
|
(PreAuthorize)targetClass.getAnnotation(PreAuthorize.class));
|
||||||
|
ConfigAttribute post = processPostInvocationAnnotations((PostFilter)targetClass.getAnnotation(PostFilter.class),
|
||||||
|
(PostAuthorize)targetClass.getAnnotation(PostAuthorize.class));
|
||||||
|
|
||||||
|
if (pre == null && post == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ConfigAttribute> attrs = new ArrayList<ConfigAttribute>(2);
|
||||||
|
if (pre != null) {
|
||||||
|
attrs.add(pre);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (post != null) {
|
||||||
|
attrs.add(post);
|
||||||
|
}
|
||||||
|
|
||||||
|
return attrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection getConfigAttributeDefinitions() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConfigAttribute processPreInvocationAnnotations(PreFilter preFilter, PreAuthorize preAuthz) {
|
||||||
|
if (preFilter == null && preAuthz == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String preAuthorizeExpression = preAuthz == null ? null : preAuthz.value();
|
||||||
|
String preFilterExpression = preFilter == null ? null : preFilter.value();
|
||||||
|
String filterObject = preFilter == null ? null : preFilter.filterTarget();
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new PreInvocationExpressionBasedMethodConfigAttribute(preFilterExpression, filterObject, preAuthorizeExpression);
|
||||||
|
} catch (ParseException e) {
|
||||||
|
throw new SecurityConfigurationException("Failed to parse expression '" + e.getExpressionString() + "'", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConfigAttribute processPostInvocationAnnotations(PostFilter postFilter, PostAuthorize postAuthz) {
|
||||||
|
if (postFilter == null && postAuthz == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String postAuthorizeExpression = postAuthz == null ? null : postAuthz.value();
|
||||||
|
String postFilterExpression = postFilter == null ? null : postFilter.value();
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new PostInvocationExpressionBasedMethodConfigAttribute(postFilterExpression, postAuthorizeExpression);
|
||||||
|
} catch (ParseException e) {
|
||||||
|
throw new SecurityConfigurationException("Failed to parse expression '" + e.getExpressionString() + "'", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,110 @@
|
|||||||
|
package org.springframework.security.expression.support;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
||||||
|
import org.springframework.core.ParameterNameDiscoverer;
|
||||||
|
import org.springframework.expression.EvaluationContext;
|
||||||
|
import org.springframework.expression.Expression;
|
||||||
|
import org.springframework.expression.spel.standard.StandardEvaluationContext;
|
||||||
|
import org.springframework.security.AccessDeniedException;
|
||||||
|
import org.springframework.security.Authentication;
|
||||||
|
import org.springframework.security.ConfigAttribute;
|
||||||
|
import org.springframework.security.ConfigAttributeDefinition;
|
||||||
|
import org.springframework.security.afterinvocation.AfterInvocationProvider;
|
||||||
|
import org.springframework.security.expression.ExpressionUtils;
|
||||||
|
import org.springframework.security.expression.SecurityExpressionRoot;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AfterInvocationProvider which handles the @PostAuthorize and @PostFilter annotation expressions.
|
||||||
|
*
|
||||||
|
* @author Luke Taylor
|
||||||
|
* @verson $Id$
|
||||||
|
* @since 2.5
|
||||||
|
*/
|
||||||
|
public class MethodExpressionAfterInvocationProvider implements AfterInvocationProvider {
|
||||||
|
|
||||||
|
protected final Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
|
private ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
|
||||||
|
|
||||||
|
public Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config, Object returnedObject)
|
||||||
|
throws AccessDeniedException {
|
||||||
|
|
||||||
|
PostInvocationExpressionBasedMethodConfigAttribute mca = findMethodAccessControlExpression(config);
|
||||||
|
|
||||||
|
if (mca == null) {
|
||||||
|
return returnedObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
StandardEvaluationContext ctx = new StandardEvaluationContext();
|
||||||
|
populateContextVariables(ctx, (MethodInvocation) object);
|
||||||
|
SecurityExpressionRoot expressionRoot = new SecurityExpressionRoot(authentication);
|
||||||
|
ctx.setRootObject(expressionRoot);
|
||||||
|
|
||||||
|
Expression postFilter = mca.getFilterExpression();
|
||||||
|
Expression postAuthorize = mca.getAuthorizeExpression();
|
||||||
|
|
||||||
|
if (postFilter != null) {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Applying PostFilter expression " + postFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (returnedObject != null) {
|
||||||
|
returnedObject = ExpressionUtils.doFilter(returnedObject, postFilter, ctx);
|
||||||
|
} else {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Return object is null, filtering will be skipped");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expressionRoot.setReturnObject(returnedObject);
|
||||||
|
|
||||||
|
if (postAuthorize != null && !ExpressionUtils.evaluateAsBoolean(postAuthorize, ctx)) {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("PostAuthorize expression rejected access");
|
||||||
|
}
|
||||||
|
throw new AccessDeniedException("Access is denied");
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnedObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void populateContextVariables(EvaluationContext ctx, MethodInvocation mi) {
|
||||||
|
Object[] args = mi.getArguments();
|
||||||
|
Object targetObject = mi.getThis();
|
||||||
|
Method method = ClassUtils.getMostSpecificMethod(mi.getMethod(), targetObject.getClass());
|
||||||
|
String[] paramNames = parameterNameDiscoverer.getParameterNames(method);
|
||||||
|
|
||||||
|
for(int i=0; i < args.length; i++) {
|
||||||
|
ctx.setVariable(paramNames[i], args[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PostInvocationExpressionBasedMethodConfigAttribute findMethodAccessControlExpression(ConfigAttributeDefinition config) {
|
||||||
|
// Find the MethodAccessControlExpression attribute
|
||||||
|
for (ConfigAttribute attribute : config.getConfigAttributes()) {
|
||||||
|
if (attribute instanceof PostInvocationExpressionBasedMethodConfigAttribute) {
|
||||||
|
return (PostInvocationExpressionBasedMethodConfigAttribute)attribute;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean supports(ConfigAttribute attribute) {
|
||||||
|
return attribute instanceof PostInvocationExpressionBasedMethodConfigAttribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean supports(Class clazz) {
|
||||||
|
return clazz.isAssignableFrom(MethodInvocation.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,109 @@
|
|||||||
|
package org.springframework.security.expression.support;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
||||||
|
import org.springframework.core.ParameterNameDiscoverer;
|
||||||
|
import org.springframework.expression.EvaluationContext;
|
||||||
|
import org.springframework.expression.Expression;
|
||||||
|
import org.springframework.expression.spel.standard.StandardEvaluationContext;
|
||||||
|
import org.springframework.security.Authentication;
|
||||||
|
import org.springframework.security.ConfigAttribute;
|
||||||
|
import org.springframework.security.ConfigAttributeDefinition;
|
||||||
|
import org.springframework.security.expression.ExpressionUtils;
|
||||||
|
import org.springframework.security.expression.SecurityExpressionRoot;
|
||||||
|
import org.springframework.security.vote.AccessDecisionVoter;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Voter which performs the actions for @PreFilter and @PostAuthorize annotations.
|
||||||
|
* <p>
|
||||||
|
* If only a @PreFilter condition is specified, it will vote to grant access, otherwise it will vote
|
||||||
|
* to grant or deny access depending on whether the @PostAuthorize expression evaluates to 'true' or 'false',
|
||||||
|
* respectively.
|
||||||
|
*
|
||||||
|
* @author Luke Taylor
|
||||||
|
* @version $Id$
|
||||||
|
* @since 2.5
|
||||||
|
*/
|
||||||
|
public class MethodExpressionVoter implements AccessDecisionVoter {
|
||||||
|
protected final Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
|
// TODO: Share this between classes
|
||||||
|
private ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
|
||||||
|
|
||||||
|
public boolean supports(ConfigAttribute attribute) {
|
||||||
|
return attribute instanceof AbstractExpressionBasedMethodConfigAttribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean supports(Class clazz) {
|
||||||
|
return clazz.isAssignableFrom(MethodInvocation.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) {
|
||||||
|
PreInvocationExpressionBasedMethodConfigAttribute mace = findMethodAccessControlExpression(config);
|
||||||
|
|
||||||
|
if (mace == null) {
|
||||||
|
// No expression based metadata, so abstain
|
||||||
|
return ACCESS_ABSTAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
StandardEvaluationContext ctx = new StandardEvaluationContext();
|
||||||
|
Object filterTarget =
|
||||||
|
populateContextVariablesAndFindFilterTarget(ctx, (MethodInvocation)object, mace.getFilterTarget());
|
||||||
|
|
||||||
|
ctx.setRootObject(new SecurityExpressionRoot(authentication));
|
||||||
|
|
||||||
|
Expression preFilter = mace.getFilterExpression();
|
||||||
|
Expression preAuthorize = mace.getAuthorizeExpression();
|
||||||
|
|
||||||
|
if (preFilter != null) {
|
||||||
|
// TODO: Allow null target if only single parameter, or single collection/array?
|
||||||
|
Object filtered = ExpressionUtils.doFilter(filterTarget, preFilter, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preAuthorize == null) {
|
||||||
|
return ACCESS_GRANTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ExpressionUtils.evaluateAsBoolean(preAuthorize, ctx) ? ACCESS_GRANTED : ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object populateContextVariablesAndFindFilterTarget(EvaluationContext ctx, MethodInvocation mi,
|
||||||
|
String filterTargetName) {
|
||||||
|
|
||||||
|
Object[] args = mi.getArguments();
|
||||||
|
Object targetObject = mi.getThis();
|
||||||
|
Method method = ClassUtils.getMostSpecificMethod(mi.getMethod(), targetObject.getClass());
|
||||||
|
Object filterTarget = null;
|
||||||
|
String[] paramNames = parameterNameDiscoverer.getParameterNames(method);
|
||||||
|
|
||||||
|
for(int i=0; i < args.length; i++) {
|
||||||
|
ctx.setVariable(paramNames[i], args[i]);
|
||||||
|
if (filterTargetName != null && paramNames[i].equals(filterTargetName)) {
|
||||||
|
filterTarget = args[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filterTargetName != null && filterTarget == null) {
|
||||||
|
throw new IllegalArgumentException("No filter target argument with name " + filterTargetName +
|
||||||
|
" found in method: " + method.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
return filterTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PreInvocationExpressionBasedMethodConfigAttribute findMethodAccessControlExpression(ConfigAttributeDefinition config) {
|
||||||
|
// Find the MethodAccessControlExpression attribute
|
||||||
|
for (ConfigAttribute attribute : config.getConfigAttributes()) {
|
||||||
|
if (attribute instanceof AbstractExpressionBasedMethodConfigAttribute) {
|
||||||
|
return (PreInvocationExpressionBasedMethodConfigAttribute)attribute;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package org.springframework.security.expression.support;
|
||||||
|
|
||||||
|
import org.springframework.expression.ParseException;
|
||||||
|
|
||||||
|
class PostInvocationExpressionBasedMethodConfigAttribute extends AbstractExpressionBasedMethodConfigAttribute {
|
||||||
|
|
||||||
|
PostInvocationExpressionBasedMethodConfigAttribute(String filterExpression, String authorizeExpression)
|
||||||
|
throws ParseException {
|
||||||
|
super(filterExpression, authorizeExpression);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package org.springframework.security.expression.support;
|
||||||
|
|
||||||
|
import org.springframework.expression.ParseException;
|
||||||
|
|
||||||
|
class PreInvocationExpressionBasedMethodConfigAttribute extends AbstractExpressionBasedMethodConfigAttribute {
|
||||||
|
private final String filterTarget;
|
||||||
|
|
||||||
|
PreInvocationExpressionBasedMethodConfigAttribute(String filterExpression, String filterTarget,
|
||||||
|
String authorizeExpression) throws ParseException {
|
||||||
|
super(filterExpression, authorizeExpression);
|
||||||
|
|
||||||
|
this.filterTarget = filterTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getFilterTarget() {
|
||||||
|
return filterTarget;
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ package org.springframework.security.intercept.method;
|
|||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.aopalliance.intercept.MethodInvocation;
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
@ -9,6 +10,7 @@ import org.apache.commons.logging.Log;
|
|||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.aspectj.lang.JoinPoint;
|
import org.aspectj.lang.JoinPoint;
|
||||||
import org.aspectj.lang.reflect.CodeSignature;
|
import org.aspectj.lang.reflect.CodeSignature;
|
||||||
|
import org.springframework.security.ConfigAttribute;
|
||||||
import org.springframework.security.ConfigAttributeDefinition;
|
import org.springframework.security.ConfigAttributeDefinition;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
@ -88,12 +90,14 @@ public abstract class AbstractFallbackMethodDefinitionSource implements MethodDe
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// We need to work it out.
|
// We need to work it out.
|
||||||
ConfigAttributeDefinition cfgAtt = computeAttributes(method, targetClass);
|
List<ConfigAttribute> attributes = computeAttributes(method, targetClass);
|
||||||
|
ConfigAttributeDefinition cfgAtt = null;
|
||||||
// Put it in the cache.
|
// Put it in the cache.
|
||||||
if (cfgAtt == null) {
|
if (attributes == null) {
|
||||||
this.attributeCache.put(cacheKey, NULL_CONFIG_ATTRIBUTE);
|
this.attributeCache.put(cacheKey, NULL_CONFIG_ATTRIBUTE);
|
||||||
}
|
} else {
|
||||||
else {
|
cfgAtt = new ConfigAttributeDefinition(attributes);
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("Adding security method [" + cacheKey + "] with attribute [" + cfgAtt + "]");
|
logger.debug("Adding security method [" + cacheKey + "] with attribute [" + cfgAtt + "]");
|
||||||
}
|
}
|
||||||
@ -110,12 +114,12 @@ public abstract class AbstractFallbackMethodDefinitionSource implements MethodDe
|
|||||||
* @param targetClass the target class for this invocation (may be <code>null</code>)
|
* @param targetClass the target class for this invocation (may be <code>null</code>)
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private ConfigAttributeDefinition computeAttributes(Method method, Class targetClass) {
|
private List<ConfigAttribute> computeAttributes(Method method, Class targetClass) {
|
||||||
// The method may be on an interface, but we need attributes from the target class.
|
// The method may be on an interface, but we need attributes from the target class.
|
||||||
// If the target class is null, the method will be unchanged.
|
// If the target class is null, the method will be unchanged.
|
||||||
Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
|
Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
|
||||||
// First try is the method in the target class.
|
// First try is the method in the target class.
|
||||||
ConfigAttributeDefinition attr = findAttributes(specificMethod, targetClass);
|
List<ConfigAttribute> attr = findAttributes(specificMethod, targetClass);
|
||||||
if (attr != null) {
|
if (attr != null) {
|
||||||
return attr;
|
return attr;
|
||||||
}
|
}
|
||||||
@ -152,7 +156,7 @@ public abstract class AbstractFallbackMethodDefinitionSource implements MethodDe
|
|||||||
* @param targetClass the target class for the invocation (may be <code>null</code>)
|
* @param targetClass the target class for the invocation (may be <code>null</code>)
|
||||||
* @return the security metadata (or null if no metadata applies)
|
* @return the security metadata (or null if no metadata applies)
|
||||||
*/
|
*/
|
||||||
protected abstract ConfigAttributeDefinition findAttributes(Method method, Class targetClass);
|
protected abstract List<ConfigAttribute> findAttributes(Method method, Class targetClass);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtains the security metadata registered against the specified class.
|
* Obtains the security metadata registered against the specified class.
|
||||||
@ -166,7 +170,7 @@ public abstract class AbstractFallbackMethodDefinitionSource implements MethodDe
|
|||||||
* @param clazz the target class for the invocation (never <code>null</code>)
|
* @param clazz the target class for the invocation (never <code>null</code>)
|
||||||
* @return the security metadata (or null if no metadata applies)
|
* @return the security metadata (or null if no metadata applies)
|
||||||
*/
|
*/
|
||||||
protected abstract ConfigAttributeDefinition findAttributes(Class clazz);
|
protected abstract List<ConfigAttribute> findAttributes(Class clazz);
|
||||||
|
|
||||||
private static class DefaultCacheKey {
|
private static class DefaultCacheKey {
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ import java.util.Map;
|
|||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||||
|
import org.springframework.security.ConfigAttribute;
|
||||||
import org.springframework.security.ConfigAttributeDefinition;
|
import org.springframework.security.ConfigAttributeDefinition;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
@ -54,10 +55,10 @@ public class MapBasedMethodDefinitionSource extends AbstractFallbackMethodDefini
|
|||||||
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
|
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
|
||||||
|
|
||||||
/** Map from RegisteredMethod to ConfigAttributeDefinition */
|
/** Map from RegisteredMethod to ConfigAttributeDefinition */
|
||||||
protected Map methodMap = new HashMap();
|
protected Map<RegisteredMethod, List<? extends ConfigAttribute>> methodMap = new HashMap();
|
||||||
|
|
||||||
/** Map from RegisteredMethod to name pattern used for registration */
|
/** Map from RegisteredMethod to name pattern used for registration */
|
||||||
private Map nameMap = new HashMap();
|
private Map<RegisteredMethod, String> nameMap = new HashMap();
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
//~ Methods ========================================================================================================
|
||||||
|
|
||||||
@ -73,21 +74,21 @@ public class MapBasedMethodDefinitionSource extends AbstractFallbackMethodDefini
|
|||||||
|
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
Map.Entry entry = (Map.Entry) iterator.next();
|
Map.Entry entry = (Map.Entry) iterator.next();
|
||||||
addSecureMethod((String)entry.getKey(), (ConfigAttributeDefinition)entry.getValue());
|
addSecureMethod((String)entry.getKey(), (List<ConfigAttribute>)entry.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation does not support class-level attributes.
|
* Implementation does not support class-level attributes.
|
||||||
*/
|
*/
|
||||||
protected ConfigAttributeDefinition findAttributes(Class clazz) {
|
protected List<ConfigAttribute> findAttributes(Class clazz) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will walk the method inheritance tree to find the most specific declaration applicable.
|
* Will walk the method inheritance tree to find the most specific declaration applicable.
|
||||||
*/
|
*/
|
||||||
protected ConfigAttributeDefinition findAttributes(Method method, Class targetClass) {
|
protected List<ConfigAttribute> findAttributes(Method method, Class targetClass) {
|
||||||
if (targetClass == null) {
|
if (targetClass == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -95,10 +96,10 @@ public class MapBasedMethodDefinitionSource extends AbstractFallbackMethodDefini
|
|||||||
return findAttributesSpecifiedAgainst(method, targetClass);
|
return findAttributesSpecifiedAgainst(method, targetClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConfigAttributeDefinition findAttributesSpecifiedAgainst(Method method, Class clazz) {
|
private List<ConfigAttribute> findAttributesSpecifiedAgainst(Method method, Class clazz) {
|
||||||
RegisteredMethod registeredMethod = new RegisteredMethod(method, clazz);
|
RegisteredMethod registeredMethod = new RegisteredMethod(method, clazz);
|
||||||
if (methodMap.containsKey(registeredMethod)) {
|
if (methodMap.containsKey(registeredMethod)) {
|
||||||
return (ConfigAttributeDefinition) methodMap.get(registeredMethod);
|
return (List<ConfigAttribute>) methodMap.get(registeredMethod);
|
||||||
}
|
}
|
||||||
// Search superclass
|
// Search superclass
|
||||||
if (clazz.getSuperclass() != null) {
|
if (clazz.getSuperclass() != null) {
|
||||||
@ -114,7 +115,7 @@ public class MapBasedMethodDefinitionSource extends AbstractFallbackMethodDefini
|
|||||||
* @param name type and method name, separated by a dot
|
* @param name type and method name, separated by a dot
|
||||||
* @param attr required authorities associated with the method
|
* @param attr required authorities associated with the method
|
||||||
*/
|
*/
|
||||||
public void addSecureMethod(String name, ConfigAttributeDefinition attr) {
|
public void addSecureMethod(String name, List<? extends ConfigAttribute> attr) {
|
||||||
int lastDotIndex = name.lastIndexOf(".");
|
int lastDotIndex = name.lastIndexOf(".");
|
||||||
|
|
||||||
if (lastDotIndex == -1) {
|
if (lastDotIndex == -1) {
|
||||||
@ -138,7 +139,7 @@ public class MapBasedMethodDefinitionSource extends AbstractFallbackMethodDefini
|
|||||||
* @param mappedName mapped method name, which the javaType has declared or inherited
|
* @param mappedName mapped method name, which the javaType has declared or inherited
|
||||||
* @param attr required authorities associated with the method
|
* @param attr required authorities associated with the method
|
||||||
*/
|
*/
|
||||||
public void addSecureMethod(Class javaType, String mappedName, ConfigAttributeDefinition attr) {
|
public void addSecureMethod(Class javaType, String mappedName, List<? extends ConfigAttribute> attr) {
|
||||||
String name = javaType.getName() + '.' + mappedName;
|
String name = javaType.getName() + '.' + mappedName;
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
@ -187,7 +188,7 @@ public class MapBasedMethodDefinitionSource extends AbstractFallbackMethodDefini
|
|||||||
* the existing match will be retained, so that if this method is called for a more general pointcut
|
* the existing match will be retained, so that if this method is called for a more general pointcut
|
||||||
* it will not override a more specific one which has already been added. This
|
* it will not override a more specific one which has already been added. This
|
||||||
*/
|
*/
|
||||||
public void addSecureMethod(Class javaType, Method method, ConfigAttributeDefinition attr) {
|
public void addSecureMethod(Class javaType, Method method, List<? extends ConfigAttribute> attr) {
|
||||||
RegisteredMethod key = new RegisteredMethod(method, javaType);
|
RegisteredMethod key = new RegisteredMethod(method, javaType);
|
||||||
|
|
||||||
if (methodMap.containsKey(key)) {
|
if (methodMap.containsKey(key)) {
|
||||||
@ -204,7 +205,7 @@ public class MapBasedMethodDefinitionSource extends AbstractFallbackMethodDefini
|
|||||||
* @param method the method to be secured
|
* @param method the method to be secured
|
||||||
* @param attr required authorities associated with the method
|
* @param attr required authorities associated with the method
|
||||||
*/
|
*/
|
||||||
private void addSecureMethod(RegisteredMethod method, ConfigAttributeDefinition attr) {
|
private void addSecureMethod(RegisteredMethod method, List<? extends ConfigAttribute> attr) {
|
||||||
Assert.notNull(method, "RegisteredMethod required");
|
Assert.notNull(method, "RegisteredMethod required");
|
||||||
Assert.notNull(attr, "Configuration attribute required");
|
Assert.notNull(attr, "Configuration attribute required");
|
||||||
if (logger.isInfoEnabled()) {
|
if (logger.isInfoEnabled()) {
|
||||||
@ -219,7 +220,13 @@ public class MapBasedMethodDefinitionSource extends AbstractFallbackMethodDefini
|
|||||||
* @return the attributes explicitly defined against this bean
|
* @return the attributes explicitly defined against this bean
|
||||||
*/
|
*/
|
||||||
public Collection getConfigAttributeDefinitions() {
|
public Collection getConfigAttributeDefinitions() {
|
||||||
return Collections.unmodifiableCollection(methodMap.values());
|
List<ConfigAttributeDefinition> configAttrs = new ArrayList<ConfigAttributeDefinition>(methodMap.values().size());
|
||||||
|
|
||||||
|
for(List<? extends ConfigAttribute> attrList : methodMap.values()) {
|
||||||
|
configAttrs.add(new ConfigAttributeDefinition(attrList));
|
||||||
|
}
|
||||||
|
|
||||||
|
return configAttrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,71 +0,0 @@
|
|||||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
|
||||||
*
|
|
||||||
* 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.security.intercept.method;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
|
||||||
import org.springframework.metadata.Attributes;
|
|
||||||
import org.springframework.security.ConfigAttribute;
|
|
||||||
import org.springframework.security.ConfigAttributeDefinition;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides {@link ConfigAttributeDefinition}s for a method signature (via the <tt>lookupAttributes</tt> method)
|
|
||||||
* by delegating to a configured {@link Attributes} object. The latter may use Commons attributes
|
|
||||||
* or some other approach to determine the <tt>ConfigAttribute</tt>s which apply.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Note that attributes defined against parent classes (either for their methods or interfaces) are not
|
|
||||||
* detected. The attributes must be defined against an explicit method or interface on the intercepted class.
|
|
||||||
* <p>
|
|
||||||
*
|
|
||||||
* Attributes detected that do not implement {@link ConfigAttribute} will be ignored.
|
|
||||||
*
|
|
||||||
* @author Cameron Braid
|
|
||||||
* @author Ben Alex
|
|
||||||
* @version $Id$
|
|
||||||
*/
|
|
||||||
public class MethodDefinitionAttributes extends AbstractFallbackMethodDefinitionSource implements InitializingBean {
|
|
||||||
//~ Instance fields ================================================================================================
|
|
||||||
|
|
||||||
private Attributes attributes;
|
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
|
||||||
|
|
||||||
public void afterPropertiesSet() throws Exception {
|
|
||||||
Assert.notNull(attributes, "attributes required");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection getConfigAttributeDefinitions() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ConfigAttributeDefinition findAttributes(Class clazz) {
|
|
||||||
return ConfigAttributeDefinition.createFiltered(attributes.getAttributes(clazz));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ConfigAttributeDefinition findAttributes(Method method, Class targetClass) {
|
|
||||||
return ConfigAttributeDefinition.createFiltered(attributes.getAttributes(method));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAttributes(Attributes attributes) {
|
|
||||||
Assert.notNull(attributes, "Attributes required");
|
|
||||||
this.attributes = attributes;
|
|
||||||
}
|
|
||||||
}
|
|
@ -15,7 +15,8 @@
|
|||||||
|
|
||||||
package org.springframework.security.intercept.method;
|
package org.springframework.security.intercept.method;
|
||||||
|
|
||||||
import org.springframework.security.ConfigAttributeDefinition;
|
import org.springframework.security.ConfigAttribute;
|
||||||
|
import org.springframework.security.SecurityConfig;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
@ -25,7 +26,9 @@ import org.springframework.util.StringUtils;
|
|||||||
|
|
||||||
import java.beans.PropertyEditorSupport;
|
import java.beans.PropertyEditorSupport;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
@ -65,8 +68,13 @@ public class MethodDefinitionSourceEditor extends PropertyEditorSupport {
|
|||||||
String value = props.getProperty(name);
|
String value = props.getProperty(name);
|
||||||
|
|
||||||
String[] tokens = StringUtils.commaDelimitedListToStringArray(value);
|
String[] tokens = StringUtils.commaDelimitedListToStringArray(value);
|
||||||
|
List<ConfigAttribute> attributes = new ArrayList<ConfigAttribute>(tokens.length);
|
||||||
|
|
||||||
mappings.put(name, new ConfigAttributeDefinition(tokens));
|
for(String token : tokens) {
|
||||||
|
attributes.add(new SecurityConfig(token));
|
||||||
|
}
|
||||||
|
|
||||||
|
mappings.put(name, attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
setValue(new MapBasedMethodDefinitionSource(mappings));
|
setValue(new MapBasedMethodDefinitionSource(mappings));
|
||||||
|
@ -4,6 +4,7 @@ import java.lang.reflect.Method;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -14,6 +15,7 @@ import org.aspectj.weaver.tools.PointcutParser;
|
|||||||
import org.aspectj.weaver.tools.PointcutPrimitive;
|
import org.aspectj.weaver.tools.PointcutPrimitive;
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||||
|
import org.springframework.security.ConfigAttribute;
|
||||||
import org.springframework.security.ConfigAttributeDefinition;
|
import org.springframework.security.ConfigAttributeDefinition;
|
||||||
import org.springframework.security.intercept.method.aopalliance.MethodDefinitionSourceAdvisor;
|
import org.springframework.security.intercept.method.aopalliance.MethodDefinitionSourceAdvisor;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
@ -57,7 +59,7 @@ public final class ProtectPointcutPostProcessor implements BeanPostProcessor {
|
|||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(ProtectPointcutPostProcessor.class);
|
private static final Log logger = LogFactory.getLog(ProtectPointcutPostProcessor.class);
|
||||||
|
|
||||||
private Map pointcutMap = new LinkedHashMap(); /** Key: string-based pointcut, value: ConfigAttributeDefinition */
|
private Map<String,List<ConfigAttribute>> pointcutMap = new LinkedHashMap();
|
||||||
private MapBasedMethodDefinitionSource mapBasedMethodDefinitionSource;
|
private MapBasedMethodDefinitionSource mapBasedMethodDefinitionSource;
|
||||||
private PointcutParser parser;
|
private PointcutParser parser;
|
||||||
|
|
||||||
@ -119,7 +121,7 @@ public final class ProtectPointcutPostProcessor implements BeanPostProcessor {
|
|||||||
|
|
||||||
// Handle accordingly
|
// Handle accordingly
|
||||||
if (matches) {
|
if (matches) {
|
||||||
ConfigAttributeDefinition attr = (ConfigAttributeDefinition) pointcutMap.get(expression.getPointcutExpression());
|
List<ConfigAttribute> attr = pointcutMap.get(expression.getPointcutExpression());
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("AspectJ pointcut expression '" + expression.getPointcutExpression() + "' matches target class '" + targetClass.getName() + "' (bean ID '" + beanName + "') for method '" + method + "'; registering security configuration attribute '" + attr + "'");
|
logger.debug("AspectJ pointcut expression '" + expression.getPointcutExpression() + "' matches target class '" + targetClass.getName() + "' (bean ID '" + beanName + "') for method '" + method + "'; registering security configuration attribute '" + attr + "'");
|
||||||
@ -131,18 +133,17 @@ public final class ProtectPointcutPostProcessor implements BeanPostProcessor {
|
|||||||
return matches;
|
return matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPointcutMap(Map map) {
|
public void setPointcutMap(Map<String, List<ConfigAttribute>> map) {
|
||||||
Assert.notEmpty(map);
|
Assert.notEmpty(map);
|
||||||
Iterator i = map.keySet().iterator();
|
Iterator i = map.keySet().iterator();
|
||||||
while (i.hasNext()) {
|
while (i.hasNext()) {
|
||||||
String expression = i.next().toString();
|
String expression = i.next().toString();
|
||||||
Object value = map.get(expression);
|
List<ConfigAttribute> value = map.get(expression);
|
||||||
Assert.isInstanceOf(ConfigAttributeDefinition.class, value, "Map keys must be instances of ConfigAttributeDefinition");
|
addPointcut(expression, value);
|
||||||
addPointcut(expression, (ConfigAttributeDefinition) value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addPointcut(String pointcutExpression, ConfigAttributeDefinition definition) {
|
private void addPointcut(String pointcutExpression, List<ConfigAttribute> definition) {
|
||||||
Assert.hasText(pointcutExpression, "An AspectJ pointcut expression is required");
|
Assert.hasText(pointcutExpression, "An AspectJ pointcut expression is required");
|
||||||
Assert.notNull(definition, "ConfigAttributeDefinition required");
|
Assert.notNull(definition, "ConfigAttributeDefinition required");
|
||||||
pointcutExpression = replaceBooleanOperators(pointcutExpression);
|
pointcutExpression = replaceBooleanOperators(pointcutExpression);
|
||||||
|
@ -13,9 +13,9 @@ public class InMemoryXmlApplicationContext extends AbstractXmlApplicationContext
|
|||||||
" xmlns:b='http://www.springframework.org/schema/beans'\n" +
|
" xmlns:b='http://www.springframework.org/schema/beans'\n" +
|
||||||
" xmlns:aop='http://www.springframework.org/schema/aop'\n" +
|
" xmlns:aop='http://www.springframework.org/schema/aop'\n" +
|
||||||
" xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'\n" +
|
" xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'\n" +
|
||||||
" xsi:schemaLocation='http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd\n" +
|
" xsi:schemaLocation='http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\n" +
|
||||||
"http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd\n" +
|
"http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd\n" +
|
||||||
"http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.2.xsd'>\n";
|
"http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.5.xsd'>\n";
|
||||||
private static final String BEANS_CLOSE = "</b:beans>\n";
|
private static final String BEANS_CLOSE = "</b:beans>\n";
|
||||||
|
|
||||||
Resource inMemoryXml;
|
Resource inMemoryXml;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-2.0.4.xsd
|
http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-2.5.xsd
|
||||||
http\://www.springframework.org/schema/security/spring-security-2.0.xsd=org/springframework/security/config/spring-security-2.0.xsd
|
http\://www.springframework.org/schema/security/spring-security-2.0.xsd=org/springframework/security/config/spring-security-2.0.xsd
|
||||||
http\://www.springframework.org/schema/security/spring-security-2.0.1.xsd=org/springframework/security/config/spring-security-2.0.1.xsd
|
http\://www.springframework.org/schema/security/spring-security-2.0.1.xsd=org/springframework/security/config/spring-security-2.0.1.xsd
|
||||||
http\://www.springframework.org/schema/security/spring-security-2.0.2.xsd=org/springframework/security/config/spring-security-2.0.2.xsd
|
http\://www.springframework.org/schema/security/spring-security-2.0.2.xsd=org/springframework/security/config/spring-security-2.0.2.xsd
|
||||||
http\://www.springframework.org/schema/security/spring-security-2.0.4.xsd=org/springframework/security/config/spring-security-2.0.4.xsd
|
http\://www.springframework.org/schema/security/spring-security-2.0.4.xsd=org/springframework/security/config/spring-security-2.0.4.xsd
|
||||||
|
http\://www.springframework.org/schema/security/spring-security-2.5.xsd=org/springframework/security/config/spring-security-2.5.xsd
|
||||||
|
@ -15,9 +15,13 @@
|
|||||||
|
|
||||||
package org.springframework.security.annotation;
|
package org.springframework.security.annotation;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.annotation.security.RolesAllowed;
|
import javax.annotation.security.RolesAllowed;
|
||||||
import javax.annotation.security.PermitAll;
|
import javax.annotation.security.PermitAll;
|
||||||
|
|
||||||
|
import org.springframework.security.expression.annotation.PreAuthorize;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
@ -28,6 +32,7 @@ public interface BusinessService {
|
|||||||
|
|
||||||
@Secured({"ROLE_ADMIN"})
|
@Secured({"ROLE_ADMIN"})
|
||||||
@RolesAllowed({"ROLE_ADMIN"})
|
@RolesAllowed({"ROLE_ADMIN"})
|
||||||
|
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||||
public void someAdminMethod();
|
public void someAdminMethod();
|
||||||
|
|
||||||
@Secured({"ROLE_USER", "ROLE_ADMIN"})
|
@Secured({"ROLE_USER", "ROLE_ADMIN"})
|
||||||
@ -45,4 +50,11 @@ public interface BusinessService {
|
|||||||
public int someOther(String s);
|
public int someOther(String s);
|
||||||
|
|
||||||
public int someOther(int input);
|
public int someOther(int input);
|
||||||
|
|
||||||
|
public List methodReturningAList(List someList);
|
||||||
|
|
||||||
|
public Object[] methodReturningAnArray(Object[] someArray);
|
||||||
|
|
||||||
|
public List methodReturningAList(String userName, String extraParam);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package org.springframework.security.annotation;
|
package org.springframework.security.annotation;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Joe Scalise
|
* @author Joe Scalise
|
||||||
@ -33,4 +36,17 @@ public class BusinessServiceImpl<E extends Entity> implements BusinessService {
|
|||||||
public int someOther(int input) {
|
public int someOther(int input) {
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List methodReturningAList(List someList) {
|
||||||
|
return someList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List methodReturningAList(String userName, String arg2) {
|
||||||
|
return new ArrayList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] methodReturningAnArray(Object[] someArray) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package org.springframework.security.annotation;
|
package org.springframework.security.annotation;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.annotation.security.RolesAllowed;
|
import javax.annotation.security.RolesAllowed;
|
||||||
import javax.annotation.security.PermitAll;
|
import javax.annotation.security.PermitAll;
|
||||||
|
|
||||||
@ -34,4 +37,17 @@ public class Jsr250BusinessServiceImpl implements BusinessService {
|
|||||||
public int someOther(int input) {
|
public int someOther(int input) {
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List methodReturningAList(List someList) {
|
||||||
|
return someList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List methodReturningAList(String userName, String arg2) {
|
||||||
|
return new ArrayList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] methodReturningAnArray(Object[] someArray) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ package org.springframework.security.annotation;
|
|||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.annotation.security.DenyAll;
|
import javax.annotation.security.DenyAll;
|
||||||
import javax.annotation.security.PermitAll;
|
import javax.annotation.security.PermitAll;
|
||||||
import javax.annotation.security.RolesAllowed;
|
import javax.annotation.security.RolesAllowed;
|
||||||
@ -9,6 +11,7 @@ import javax.annotation.security.RolesAllowed;
|
|||||||
import junit.framework.Assert;
|
import junit.framework.Assert;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.springframework.security.ConfigAttribute;
|
||||||
import org.springframework.security.ConfigAttributeDefinition;
|
import org.springframework.security.ConfigAttributeDefinition;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -17,56 +20,56 @@ import org.springframework.security.ConfigAttributeDefinition;
|
|||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class Jsr250MethodDefinitionSourceTests {
|
public class Jsr250MethodDefinitionSourceTests {
|
||||||
Jsr250MethodDefinitionSource mds = new Jsr250MethodDefinitionSource();
|
Jsr250MethodDefinitionSource mds = new Jsr250MethodDefinitionSource();
|
||||||
A a = new A();
|
A a = new A();
|
||||||
UserAllowedClass userAllowed = new UserAllowedClass();
|
UserAllowedClass userAllowed = new UserAllowedClass();
|
||||||
DenyAllClass denyAll = new DenyAllClass();
|
DenyAllClass denyAll = new DenyAllClass();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void methodWithRolesAllowedHasCorrectAttribute() throws Exception {
|
public void methodWithRolesAllowedHasCorrectAttribute() throws Exception {
|
||||||
ConfigAttributeDefinition accessAttributes = mds.findAttributes(a.getClass().getMethod("adminMethod"), null);
|
List<ConfigAttribute> accessAttributes = mds.findAttributes(a.getClass().getMethod("adminMethod"), null);
|
||||||
assertEquals(1, accessAttributes.getConfigAttributes().size());
|
assertEquals(1, accessAttributes.size());
|
||||||
assertEquals("ADMIN", accessAttributes.getConfigAttributes().iterator().next().toString());
|
assertEquals("ADMIN", accessAttributes.get(0).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void permitAllMethodHasPermitAllAttribute() throws Exception {
|
public void permitAllMethodHasPermitAllAttribute() throws Exception {
|
||||||
ConfigAttributeDefinition accessAttributes = mds.findAttributes(a.getClass().getMethod("permitAllMethod"), null);
|
List<ConfigAttribute> accessAttributes = mds.findAttributes(a.getClass().getMethod("permitAllMethod"), null);
|
||||||
assertEquals(1, accessAttributes.getConfigAttributes().size());
|
assertEquals(1, accessAttributes.size());
|
||||||
assertEquals("javax.annotation.security.PermitAll", accessAttributes.getConfigAttributes().iterator().next().toString());
|
assertEquals("javax.annotation.security.PermitAll", accessAttributes.get(0).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void noRoleMethodHasDenyAllAttributeWithDenyAllClass() throws Exception {
|
public void noRoleMethodHasDenyAllAttributeWithDenyAllClass() throws Exception {
|
||||||
ConfigAttributeDefinition accessAttributes = mds.findAttributes(denyAll.getClass());
|
List<ConfigAttribute> accessAttributes = mds.findAttributes(denyAll.getClass());
|
||||||
assertEquals(1, accessAttributes.getConfigAttributes().size());
|
assertEquals(1, accessAttributes.size());
|
||||||
assertEquals("javax.annotation.security.DenyAll", accessAttributes.getConfigAttributes().iterator().next().toString());
|
assertEquals("javax.annotation.security.DenyAll", accessAttributes.get(0).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void adminMethodHasAdminAttributeWithDenyAllClass() throws Exception {
|
public void adminMethodHasAdminAttributeWithDenyAllClass() throws Exception {
|
||||||
ConfigAttributeDefinition accessAttributes = mds.findAttributes(denyAll.getClass().getMethod("adminMethod"), null);
|
List<ConfigAttribute> accessAttributes = mds.findAttributes(denyAll.getClass().getMethod("adminMethod"), null);
|
||||||
assertEquals(1, accessAttributes.getConfigAttributes().size());
|
assertEquals(1, accessAttributes.size());
|
||||||
assertEquals("ADMIN", accessAttributes.getConfigAttributes().iterator().next().toString());
|
assertEquals("ADMIN", accessAttributes.get(0).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void noRoleMethodHasNoAttributes() throws Exception {
|
public void noRoleMethodHasNoAttributes() throws Exception {
|
||||||
ConfigAttributeDefinition accessAttributes = mds.findAttributes(a.getClass().getMethod("noRoleMethod"), null);
|
List<ConfigAttribute> accessAttributes = mds.findAttributes(a.getClass().getMethod("noRoleMethod"), null);
|
||||||
Assert.assertNull(accessAttributes);
|
Assert.assertNull(accessAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void classRoleIsAppliedToNoRoleMethod() throws Exception {
|
public void classRoleIsAppliedToNoRoleMethod() throws Exception {
|
||||||
ConfigAttributeDefinition accessAttributes = mds.findAttributes(userAllowed.getClass().getMethod("noRoleMethod"), null);
|
List<ConfigAttribute> accessAttributes = mds.findAttributes(userAllowed.getClass().getMethod("noRoleMethod"), null);
|
||||||
Assert.assertNull(accessAttributes);
|
Assert.assertNull(accessAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void methodRoleOverridesClassRole() throws Exception {
|
public void methodRoleOverridesClassRole() throws Exception {
|
||||||
ConfigAttributeDefinition accessAttributes = mds.findAttributes(userAllowed.getClass().getMethod("adminMethod"), null);
|
List<ConfigAttribute> accessAttributes = mds.findAttributes(userAllowed.getClass().getMethod("adminMethod"), null);
|
||||||
assertEquals(1, accessAttributes.getConfigAttributes().size());
|
assertEquals(1, accessAttributes.size());
|
||||||
assertEquals("ADMIN", accessAttributes.getConfigAttributes().iterator().next().toString());
|
assertEquals("ADMIN", accessAttributes.get(0).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ Inner Classes ======================================================================================================
|
//~ Inner Classes ======================================================================================================
|
||||||
|
@ -15,11 +15,13 @@
|
|||||||
package org.springframework.security.annotation;
|
package org.springframework.security.annotation;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.security.ConfigAttribute;
|
||||||
import org.springframework.security.ConfigAttributeDefinition;
|
import org.springframework.security.ConfigAttributeDefinition;
|
||||||
import org.springframework.security.SecurityConfig;
|
import org.springframework.security.SecurityConfig;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
@ -50,22 +52,19 @@ public class SecuredMethodDefinitionSourceTests extends TestCase {
|
|||||||
fail("Should be a superMethod called 'someUserMethod3' on class!");
|
fail("Should be a superMethod called 'someUserMethod3' on class!");
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigAttributeDefinition attrs = this.mds.findAttributes(method, DepartmentServiceImpl.class);
|
List<ConfigAttribute> attrs = mds.findAttributes(method, DepartmentServiceImpl.class);
|
||||||
|
|
||||||
assertNotNull(attrs);
|
assertNotNull(attrs);
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("attrs: " + StringUtils.collectionToCommaDelimitedString(attrs.getConfigAttributes()));
|
logger.debug("attrs: " + StringUtils.collectionToCommaDelimitedString(attrs));
|
||||||
}
|
}
|
||||||
|
|
||||||
// expect 1 attribute
|
// expect 1 attribute
|
||||||
assertTrue("Did not find 1 attribute", attrs.getConfigAttributes().size() == 1);
|
assertTrue("Did not find 1 attribute", attrs.size() == 1);
|
||||||
|
|
||||||
// should have 1 SecurityConfig
|
// should have 1 SecurityConfig
|
||||||
for (Object obj : attrs.getConfigAttributes()) {
|
for (ConfigAttribute sc : attrs) {
|
||||||
assertTrue(obj instanceof SecurityConfig);
|
|
||||||
|
|
||||||
SecurityConfig sc = (SecurityConfig) obj;
|
|
||||||
assertEquals("Found an incorrect role", "ROLE_ADMIN", sc.getAttribute());
|
assertEquals("Found an incorrect role", "ROLE_ADMIN", sc.getAttribute());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,37 +76,35 @@ public class SecuredMethodDefinitionSourceTests extends TestCase {
|
|||||||
fail("Should be a superMethod called 'someUserMethod3' on class!");
|
fail("Should be a superMethod called 'someUserMethod3' on class!");
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigAttributeDefinition superAttrs = this.mds.findAttributes(superMethod, DepartmentServiceImpl.class);
|
List<ConfigAttribute> superAttrs = this.mds.findAttributes(superMethod, DepartmentServiceImpl.class);
|
||||||
|
|
||||||
assertNotNull(superAttrs);
|
assertNotNull(superAttrs);
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("superAttrs: " + StringUtils.collectionToCommaDelimitedString(superAttrs.getConfigAttributes()));
|
logger.debug("superAttrs: " + StringUtils.collectionToCommaDelimitedString(superAttrs));
|
||||||
}
|
}
|
||||||
|
|
||||||
// This part of the test relates to SEC-274
|
// This part of the test relates to SEC-274
|
||||||
// expect 1 attribute
|
// expect 1 attribute
|
||||||
assertTrue("Did not find 1 attribute", superAttrs.getConfigAttributes().size() == 1);
|
assertEquals("Did not find 1 attribute", 1, superAttrs.size());
|
||||||
// should have 1 SecurityConfig
|
// should have 1 SecurityConfig
|
||||||
for (Object obj : superAttrs.getConfigAttributes()) {
|
for (ConfigAttribute sc : superAttrs) {
|
||||||
assertTrue(obj instanceof SecurityConfig);
|
|
||||||
SecurityConfig sc = (SecurityConfig) obj;
|
|
||||||
assertEquals("Found an incorrect role", "ROLE_ADMIN", sc.getAttribute());
|
assertEquals("Found an incorrect role", "ROLE_ADMIN", sc.getAttribute());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testGetAttributesClass() {
|
public void testGetAttributesClass() {
|
||||||
ConfigAttributeDefinition attrs = this.mds.findAttributes(BusinessService.class);
|
List<ConfigAttribute> attrs = this.mds.findAttributes(BusinessService.class);
|
||||||
|
|
||||||
assertNotNull(attrs);
|
assertNotNull(attrs);
|
||||||
|
|
||||||
// expect 1 annotation
|
// expect 1 annotation
|
||||||
assertTrue(attrs.getConfigAttributes().size() == 1);
|
assertEquals(1, attrs.size());
|
||||||
|
|
||||||
// should have 1 SecurityConfig
|
// should have 1 SecurityConfig
|
||||||
SecurityConfig sc = (SecurityConfig) attrs.getConfigAttributes().iterator().next();
|
SecurityConfig sc = ((SecurityConfig) attrs.get(0));
|
||||||
|
|
||||||
assertTrue(sc.getAttribute().equals("ROLE_USER"));
|
assertEquals("ROLE_USER", sc.getAttribute());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testGetAttributesMethod() {
|
public void testGetAttributesMethod() {
|
||||||
@ -119,21 +116,19 @@ public class SecuredMethodDefinitionSourceTests extends TestCase {
|
|||||||
fail("Should be a method called 'someUserAndAdminMethod' on class!");
|
fail("Should be a method called 'someUserAndAdminMethod' on class!");
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigAttributeDefinition attrs = this.mds.findAttributes(method, BusinessService.class);
|
List<ConfigAttribute> attrs = this.mds.findAttributes(method, BusinessService.class);
|
||||||
|
|
||||||
assertNotNull(attrs);
|
assertNotNull(attrs);
|
||||||
|
|
||||||
// expect 2 attributes
|
// expect 2 attributes
|
||||||
assertTrue(attrs.getConfigAttributes().size() == 2);
|
assertEquals(2, attrs.size());
|
||||||
|
|
||||||
boolean user = false;
|
boolean user = false;
|
||||||
boolean admin = false;
|
boolean admin = false;
|
||||||
|
|
||||||
// should have 2 SecurityConfigs
|
// should have 2 SecurityConfigs
|
||||||
for (Object obj : attrs.getConfigAttributes()) {
|
for (ConfigAttribute sc : attrs) {
|
||||||
assertTrue(obj instanceof SecurityConfig);
|
assertTrue(sc instanceof SecurityConfig);
|
||||||
|
|
||||||
SecurityConfig sc = (SecurityConfig) obj;
|
|
||||||
|
|
||||||
if (sc.getAttribute().equals("ROLE_USER")) {
|
if (sc.getAttribute().equals("ROLE_USER")) {
|
||||||
user = true;
|
user = true;
|
||||||
|
@ -33,8 +33,8 @@ public class CustomAfterInvocationProviderBeanDefinitionDecoratorTests {
|
|||||||
MethodSecurityInterceptor msi = (MethodSecurityInterceptor) appContext.getBean(BeanIds.METHOD_SECURITY_INTERCEPTOR);
|
MethodSecurityInterceptor msi = (MethodSecurityInterceptor) appContext.getBean(BeanIds.METHOD_SECURITY_INTERCEPTOR);
|
||||||
AfterInvocationProviderManager apm = (AfterInvocationProviderManager) msi.getAfterInvocationManager();
|
AfterInvocationProviderManager apm = (AfterInvocationProviderManager) msi.getAfterInvocationManager();
|
||||||
assertNotNull(apm);
|
assertNotNull(apm);
|
||||||
assertEquals(1, apm.getProviders().size());
|
assertEquals(2, apm.getProviders().size());
|
||||||
assertTrue(apm.getProviders().get(0) instanceof MockAfterInvocationProvider);
|
assertTrue(apm.getProviders().get(1) instanceof MockAfterInvocationProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setContext(String context) {
|
private void setContext(String context) {
|
||||||
|
@ -3,6 +3,9 @@ package org.springframework.security.config;
|
|||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.springframework.security.config.ConfigTestUtils.*;
|
import static org.springframework.security.config.ConfigTestUtils.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
||||||
@ -180,6 +183,50 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
|||||||
target.someUserMethod1();
|
target.someUserMethod1();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected=AccessDeniedException.class)
|
||||||
|
public void accessIsDeniedForHasRoleExpression() {
|
||||||
|
setContext(
|
||||||
|
"<global-method-security spel-annotations='enabled'/>" +
|
||||||
|
"<b:bean id='target' class='org.springframework.security.annotation.ExpressionProtectedBusinessServiceImpl'/>" +
|
||||||
|
AUTH_PROVIDER_XML);
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("bob","bobspassword"));
|
||||||
|
target = (BusinessService) appContext.getBean("target");
|
||||||
|
target.someAdminMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void preAndPostFilterAnnotationsWorkWithLists() {
|
||||||
|
setContext(
|
||||||
|
"<global-method-security spel-annotations='enabled'/>" +
|
||||||
|
"<b:bean id='target' class='org.springframework.security.annotation.ExpressionProtectedBusinessServiceImpl'/>" +
|
||||||
|
AUTH_PROVIDER_XML);
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("bob","bobspassword"));
|
||||||
|
target = (BusinessService) appContext.getBean("target");
|
||||||
|
List arg = new ArrayList();
|
||||||
|
arg.add("joe");
|
||||||
|
arg.add("bob");
|
||||||
|
arg.add("sam");
|
||||||
|
List result = target.methodReturningAList(arg);
|
||||||
|
// Expression is (filterObject == name or filterObject == 'sam'), so "joe" should be gone after pre-filter
|
||||||
|
// PostFilter should remove sam from the return object
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
assertEquals("bob", result.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void preAndPostFilterAnnotationsWorkWithArrays() {
|
||||||
|
setContext(
|
||||||
|
"<global-method-security spel-annotations='enabled'/>" +
|
||||||
|
"<b:bean id='target' class='org.springframework.security.annotation.ExpressionProtectedBusinessServiceImpl'/>" +
|
||||||
|
AUTH_PROVIDER_XML);
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("bob","bobspassword"));
|
||||||
|
target = (BusinessService) appContext.getBean("target");
|
||||||
|
Object[] arg = new String[] {"joe", "bob", "sam"};
|
||||||
|
Object[] result = target.methodReturningAnArray(arg);
|
||||||
|
assertEquals(1, result.length);
|
||||||
|
assertEquals("bob", result[0]);
|
||||||
|
}
|
||||||
|
|
||||||
private void setContext(String context) {
|
private void setContext(String context) {
|
||||||
appContext = new InMemoryXmlApplicationContext(context);
|
appContext = new InMemoryXmlApplicationContext(context);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
package org.springframework.security.expression.support;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.security.ConfigAttributeDefinition;
|
||||||
|
import org.springframework.security.annotation.ExpressionProtectedBusinessServiceImpl;
|
||||||
|
import org.springframework.security.expression.support.AbstractExpressionBasedMethodConfigAttribute;
|
||||||
|
import org.springframework.security.expression.support.MethodExpressionVoter;
|
||||||
|
import org.springframework.security.providers.TestingAuthenticationToken;
|
||||||
|
import org.springframework.security.util.SimpleMethodInvocation;
|
||||||
|
import org.springframework.security.vote.AccessDecisionVoter;
|
||||||
|
|
||||||
|
public class MethodExpressionVoterTests {
|
||||||
|
private TestingAuthenticationToken joe = new TestingAuthenticationToken("joe", "joespass", "blah");
|
||||||
|
private MethodInvocation miStringArgs;
|
||||||
|
private MethodInvocation miListArg;
|
||||||
|
private List listArg;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
Method m = ExpressionProtectedBusinessServiceImpl.class.getMethod("methodReturningAList",
|
||||||
|
String.class, String.class);
|
||||||
|
miStringArgs = new SimpleMethodInvocation(new Object(), m, new String[] {"joe", "arg2Value"});
|
||||||
|
m = ExpressionProtectedBusinessServiceImpl.class.getMethod("methodReturningAList", List.class);
|
||||||
|
listArg = new ArrayList(Arrays.asList("joe", "bob"));
|
||||||
|
miListArg = new SimpleMethodInvocation(new Object(), m, new Object[] {listArg});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hasRoleExpressionAllowsUserWithRole() throws Exception {
|
||||||
|
MethodExpressionVoter am = new MethodExpressionVoter();
|
||||||
|
ConfigAttributeDefinition cad = new ConfigAttributeDefinition(new PreInvocationExpressionBasedMethodConfigAttribute(null, null, "hasRole('blah')"));
|
||||||
|
|
||||||
|
assertEquals(AccessDecisionVoter.ACCESS_GRANTED, am.vote(joe, miStringArgs, cad));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hasRoleExpressionDeniesUserWithoutRole() throws Exception {
|
||||||
|
MethodExpressionVoter am = new MethodExpressionVoter();
|
||||||
|
ConfigAttributeDefinition cad = new ConfigAttributeDefinition(new PreInvocationExpressionBasedMethodConfigAttribute(null, null, "hasRole('joedoesnt')"));
|
||||||
|
|
||||||
|
assertEquals(AccessDecisionVoter.ACCESS_DENIED, am.vote(joe, miStringArgs, cad));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void matchingArgAgainstAuthenticationNameIsSuccessful() throws Exception {
|
||||||
|
MethodExpressionVoter am = new MethodExpressionVoter();
|
||||||
|
ConfigAttributeDefinition cad = new ConfigAttributeDefinition(new PreInvocationExpressionBasedMethodConfigAttribute(null, null, "(#userName == name) and (name == 'joe')"));
|
||||||
|
|
||||||
|
assertEquals(AccessDecisionVoter.ACCESS_GRANTED, am.vote(joe, miStringArgs, cad));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void accessIsGrantedIfNoPreAuthorizeAttributeIsUsed() throws Exception {
|
||||||
|
MethodExpressionVoter am = new MethodExpressionVoter();
|
||||||
|
ConfigAttributeDefinition cad = new ConfigAttributeDefinition(new PreInvocationExpressionBasedMethodConfigAttribute("(name == 'jim')", "someList", null));
|
||||||
|
|
||||||
|
assertEquals(AccessDecisionVoter.ACCESS_GRANTED, am.vote(joe, miListArg, cad));
|
||||||
|
// All objects should have been removed, because the expression is always false
|
||||||
|
assertEquals(0, listArg.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,94 +0,0 @@
|
|||||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
|
||||||
*
|
|
||||||
* 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.security.intercept.method;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import org.springframework.security.util.SimpleMethodInvocation;
|
|
||||||
|
|
||||||
import org.aopalliance.intercept.MethodInvocation;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests {@link AbstractMethodDefinitionSource} and associated {@link ConfigAttributeDefinition}.
|
|
||||||
*
|
|
||||||
* @author Ben Alex
|
|
||||||
* @version $Id$
|
|
||||||
*/
|
|
||||||
public class AbstractMethodDefinitionSourceTests extends TestCase {
|
|
||||||
//~ Constructors ===================================================================================================
|
|
||||||
|
|
||||||
public AbstractMethodDefinitionSourceTests() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public AbstractMethodDefinitionSourceTests(String arg0) {
|
|
||||||
super(arg0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
junit.textui.TestRunner.run(AbstractMethodDefinitionSourceTests.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testDoesNotSupportAnotherObject() {
|
|
||||||
MockMethodDefinitionSource mds = new MockMethodDefinitionSource(false, true);
|
|
||||||
assertFalse(mds.supports(String.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testGetAttributesForANonMethodInvocation() {
|
|
||||||
MockMethodDefinitionSource mds = new MockMethodDefinitionSource(false, true);
|
|
||||||
|
|
||||||
try {
|
|
||||||
mds.getAttributes(new String());
|
|
||||||
fail("Should have thrown IllegalArgumentException");
|
|
||||||
} catch (IllegalArgumentException expected) {
|
|
||||||
assertTrue(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testGetAttributesForANullObject() {
|
|
||||||
MockMethodDefinitionSource mds = new MockMethodDefinitionSource(false, true);
|
|
||||||
|
|
||||||
try {
|
|
||||||
mds.getAttributes(null);
|
|
||||||
fail("Should have thrown IllegalArgumentException");
|
|
||||||
} catch (IllegalArgumentException expected) {
|
|
||||||
assertTrue(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testGetAttributesForMethodInvocation() {
|
|
||||||
MockMethodDefinitionSource mds = new MockMethodDefinitionSource(false, true);
|
|
||||||
|
|
||||||
try {
|
|
||||||
mds.getAttributes(new SimpleMethodInvocation());
|
|
||||||
fail("Should have thrown UnsupportedOperationException");
|
|
||||||
} catch (UnsupportedOperationException expected) {
|
|
||||||
assertTrue(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testSupportsMethodInvocation() {
|
|
||||||
MockMethodDefinitionSource mds = new MockMethodDefinitionSource(false, true);
|
|
||||||
assertTrue(mds.supports(MethodInvocation.class));
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,10 +3,13 @@ package org.springframework.security.intercept.method;
|
|||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.security.ConfigAttributeDefinition;
|
import org.springframework.security.ConfigAttribute;
|
||||||
|
import org.springframework.security.SecurityConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link MapBasedMethodDefinitionSource}.
|
* Tests for {@link MapBasedMethodDefinitionSource}.
|
||||||
@ -15,8 +18,8 @@ import org.springframework.security.ConfigAttributeDefinition;
|
|||||||
* @since 2.0.4
|
* @since 2.0.4
|
||||||
*/
|
*/
|
||||||
public class MapBasedMethodDefinitionSourceTests {
|
public class MapBasedMethodDefinitionSourceTests {
|
||||||
private final ConfigAttributeDefinition ROLE_A = new ConfigAttributeDefinition("ROLE_A");
|
private final List<? extends ConfigAttribute> ROLE_A = Arrays.asList(new SecurityConfig("ROLE_A"));
|
||||||
private final ConfigAttributeDefinition ROLE_B = new ConfigAttributeDefinition("ROLE_B");
|
private final List<? extends ConfigAttribute> ROLE_B = Arrays.asList(new SecurityConfig("ROLE_B"));
|
||||||
private MapBasedMethodDefinitionSource mds;
|
private MapBasedMethodDefinitionSource mds;
|
||||||
private Method someMethodString;
|
private Method someMethodString;
|
||||||
private Method someMethodInteger;
|
private Method someMethodInteger;
|
||||||
@ -32,7 +35,7 @@ public class MapBasedMethodDefinitionSourceTests {
|
|||||||
public void wildcardedMatchIsOverwrittenByMoreSpecificMatch() {
|
public void wildcardedMatchIsOverwrittenByMoreSpecificMatch() {
|
||||||
mds.addSecureMethod(MockService.class, "some*", ROLE_A);
|
mds.addSecureMethod(MockService.class, "some*", ROLE_A);
|
||||||
mds.addSecureMethod(MockService.class, "someMethod*", ROLE_B);
|
mds.addSecureMethod(MockService.class, "someMethod*", ROLE_B);
|
||||||
assertEquals(ROLE_B, mds.getAttributes(someMethodInteger, MockService.class));
|
assertEquals(ROLE_B, mds.getAttributes(someMethodInteger, MockService.class).getConfigAttributes());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -40,8 +43,8 @@ public class MapBasedMethodDefinitionSourceTests {
|
|||||||
mds.addSecureMethod(MockService.class, someMethodInteger, ROLE_A);
|
mds.addSecureMethod(MockService.class, someMethodInteger, ROLE_A);
|
||||||
mds.addSecureMethod(MockService.class, someMethodString, ROLE_B);
|
mds.addSecureMethod(MockService.class, someMethodString, ROLE_B);
|
||||||
|
|
||||||
assertEquals(ROLE_A, mds.getAttributes(someMethodInteger, MockService.class));
|
assertEquals(ROLE_A, mds.getAttributes(someMethodInteger, MockService.class).getConfigAttributes());
|
||||||
assertEquals(ROLE_B, mds.getAttributes(someMethodString, MockService.class));
|
assertEquals(ROLE_B, mds.getAttributes(someMethodString, MockService.class).getConfigAttributes());
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MockService {
|
private class MockService {
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
|
||||||
*
|
|
||||||
* 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.security.intercept.method;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
import junit.framework.Assert;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.springframework.security.ConfigAttributeDefinition;
|
|
||||||
import org.springframework.security.ITargetObject;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests {@link MethodDefinitionAttributes}.
|
|
||||||
*
|
|
||||||
* @author Cameron Braid
|
|
||||||
* @author Ben Alex
|
|
||||||
* @version $Id$
|
|
||||||
*/
|
|
||||||
public class MethodDefinitionAttributesTests {
|
|
||||||
|
|
||||||
private MethodDefinitionAttributes build() {
|
|
||||||
MethodDefinitionAttributes mda = new MethodDefinitionAttributes();
|
|
||||||
mda.setAttributes(new MockAttributes());
|
|
||||||
return mda;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testMethodsReturned() throws Exception {
|
|
||||||
Class clazz = ITargetObject.class;
|
|
||||||
Method method = clazz.getMethod("countLength", new Class[] {String.class});
|
|
||||||
ConfigAttributeDefinition result = build().findAttributes(method, ITargetObject.class);
|
|
||||||
Assert.assertEquals(1, result.getConfigAttributes().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testClassesReturned() throws Exception {
|
|
||||||
Class clazz = ITargetObject.class;
|
|
||||||
ConfigAttributeDefinition result = build().findAttributes(ITargetObject.class);
|
|
||||||
Assert.assertEquals(1, result.getConfigAttributes().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
package org.springframework.security.intercept.method;
|
package org.springframework.security.intercept.method;
|
||||||
|
|
||||||
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
|
import org.aspectj.lang.JoinPoint;
|
||||||
import org.springframework.security.ConfigAttributeDefinition;
|
import org.springframework.security.ConfigAttributeDefinition;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
@ -29,7 +31,7 @@ import java.util.Collection;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class MockMethodDefinitionSource extends AbstractMethodDefinitionSource {
|
public class MockMethodDefinitionSource implements MethodDefinitionSource {
|
||||||
//~ Instance fields ================================================================================================
|
//~ Instance fields ================================================================================================
|
||||||
|
|
||||||
private List list;
|
private List list;
|
||||||
@ -68,11 +70,16 @@ public class MockMethodDefinitionSource extends AbstractMethodDefinitionSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ConfigAttributeDefinition lookupAttributes(Method method) {
|
public ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException {
|
||||||
throw new UnsupportedOperationException("mock method not implemented");
|
throw new UnsupportedOperationException("mock method not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConfigAttributeDefinition getAttributes(Method method, Class targetClass) {
|
public ConfigAttributeDefinition getAttributes(Method method, Class targetClass) {
|
||||||
throw new UnsupportedOperationException("mock method not implemented");
|
throw new UnsupportedOperationException("mock method not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean supports(Class clazz) {
|
||||||
|
return (MethodInvocation.class.isAssignableFrom(clazz) || JoinPoint.class.isAssignableFrom(clazz));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
25
pom.xml
25
pom.xml
@ -17,6 +17,7 @@
|
|||||||
<module>acl</module>
|
<module>acl</module>
|
||||||
<module>taglibs</module>
|
<module>taglibs</module>
|
||||||
<module>itest</module>
|
<module>itest</module>
|
||||||
|
<module>spring-el</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<description>Spring Security</description>
|
<description>Spring Security</description>
|
||||||
@ -76,11 +77,16 @@
|
|||||||
</distributionManagement>
|
</distributionManagement>
|
||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
<repository>
|
||||||
<id>spring-external</id>
|
<id>com.springsource.repository.bundles.release</id>
|
||||||
<name>Spring Portfolio Release Repository</name>
|
<name>SpringSource Enterprise Bundle Repository - SpringSource Bundle Releases</name>
|
||||||
<url>http://s3.amazonaws.com/maven.springframework.org/external</url>
|
<url>http://repository.springsource.com/maven/bundles/release</url>
|
||||||
</repository>
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>com.springsource.repository.bundles.external</id>
|
||||||
|
<name>SpringSource Enterprise Bundle Repository - External Bundle Releases</name>
|
||||||
|
<url>http://repository.springsource.com/maven/bundles/external</url>
|
||||||
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
<mailingLists>
|
<mailingLists>
|
||||||
@ -634,14 +640,13 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.aspectj</groupId>
|
<groupId>org.aspectj</groupId>
|
||||||
<artifactId>aspectjweaver</artifactId>
|
<artifactId>com.springsource.org.aspectj.runtime</artifactId>
|
||||||
<optional>true</optional>
|
<version>1.6.2.RELEASE</version>
|
||||||
<version>1.5.4</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.aspectj</groupId>
|
<groupId>org.aspectj</groupId>
|
||||||
<artifactId>aspectjrt</artifactId>
|
<artifactId>com.springsource.org.aspectj.weaver</artifactId>
|
||||||
<version>1.5.4</version>
|
<version>1.6.2.RELEASE</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
|
@ -24,15 +24,6 @@
|
|||||||
<groupId>javax.servlet</groupId>
|
<groupId>javax.servlet</groupId>
|
||||||
<artifactId>servlet-api</artifactId>
|
<artifactId>servlet-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.aspectj</groupId>
|
|
||||||
<artifactId>aspectjrt</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.aspectj</groupId>
|
|
||||||
<artifactId>aspectjweaver</artifactId>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.servlet</groupId>
|
<groupId>javax.servlet</groupId>
|
||||||
<artifactId>jstl</artifactId>
|
<artifactId>jstl</artifactId>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user