mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-05-31 01:02:14 +00:00
SEC-1158: Decoupling of Pre/Post annotations implementation from Spring EL.
This commit is contained in:
parent
acd7dc1f2d
commit
14c4739605
@ -12,7 +12,6 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.security.access.expression.method.MethodExpressionVoter;
|
||||
import org.springframework.security.access.intercept.AfterInvocationProviderManager;
|
||||
import org.springframework.security.access.vote.AccessDecisionVoter;
|
||||
import org.springframework.security.access.vote.AffirmativeBased;
|
||||
@ -35,7 +34,7 @@ abstract class ConfigUtils {
|
||||
static void registerDefaultMethodAccessManagerIfNecessary(ParserContext parserContext) {
|
||||
if (!parserContext.getRegistry().containsBeanDefinition(BeanIds.METHOD_ACCESS_MANAGER)) {
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.METHOD_ACCESS_MANAGER,
|
||||
createAccessManagerBean(MethodExpressionVoter.class, RoleVoter.class, AuthenticatedVoter.class));
|
||||
createAccessManagerBean(RoleVoter.class, AuthenticatedVoter.class));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ import org.springframework.util.ClassUtils;
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 2.5
|
||||
* @since 3.0
|
||||
*/
|
||||
class ContextSourceSettingPostProcessor implements BeanFactoryPostProcessor, Ordered {
|
||||
private static final String REQUIRED_CONTEXT_SOURCE_CLASS_NAME = "org.springframework.ldap.core.support.BaseLdapPathContextSource";
|
||||
@ -27,7 +27,7 @@ class ContextSourceSettingPostProcessor implements BeanFactoryPostProcessor, Ord
|
||||
Class<?> contextSourceClass;
|
||||
|
||||
try {
|
||||
contextSourceClass = ClassUtils.forName(REQUIRED_CONTEXT_SOURCE_CLASS_NAME);
|
||||
contextSourceClass = ClassUtils.forName(REQUIRED_CONTEXT_SOURCE_CLASS_NAME, ClassUtils.getDefaultClassLoader());
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new SecurityConfigurationException("Couldn't locate: " + REQUIRED_CONTEXT_SOURCE_CLASS_NAME + ". " +
|
||||
" If you are using LDAP with Spring Security, please ensure that you include the spring-ldap " +
|
||||
|
@ -22,6 +22,10 @@ public abstract class Elements {
|
||||
public static final String LDAP_USER_SERVICE = "ldap-user-service";
|
||||
public static final String PROTECT_POINTCUT = "protect-pointcut";
|
||||
public static final String EXPRESSION_HANDLER = "expression-handler";
|
||||
public static final String INVOCATION_HANDLING = "pre-post-annotation-handling";
|
||||
public static final String INVOCATION_ATTRIBUTE_FACTORY = "invocation-attribute-factory";
|
||||
public static final String PRE_INVOCATION_ADVICE = "pre-invocation-advice";
|
||||
public static final String POST_INVOCATION_ADVICE = "post-invocation-advice";
|
||||
public static final String PROTECT = "protect";
|
||||
public static final String CONCURRENT_SESSIONS = "concurrent-session-control";
|
||||
public static final String LOGOUT = "logout";
|
||||
|
@ -1,5 +1,7 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
import static org.springframework.security.config.Elements.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@ -18,14 +20,21 @@ import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.SecurityConfig;
|
||||
import org.springframework.security.access.expression.method.MethodExpressionAfterInvocationProvider;
|
||||
import org.springframework.security.access.expression.method.MethodExpressionVoter;
|
||||
import org.springframework.security.access.expression.support.DefaultMethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.annotation.Jsr250MethodSecurityMetadataSource;
|
||||
import org.springframework.security.access.annotation.Jsr250Voter;
|
||||
import org.springframework.security.access.annotation.SecuredAnnotationSecurityMetadataSource;
|
||||
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.expression.method.ExpressionBasedAnnotationAttributeFactory;
|
||||
import org.springframework.security.access.expression.method.ExpressionBasedPostInvocationAdvice;
|
||||
import org.springframework.security.access.expression.method.ExpressionBasedPreInvocationAdvice;
|
||||
import org.springframework.security.access.intercept.method.DelegatingMethodSecurityMetadataSource;
|
||||
import org.springframework.security.access.intercept.method.MapBasedMethodSecurityMetadataSource;
|
||||
import org.springframework.security.access.intercept.method.ProtectPointcutPostProcessor;
|
||||
import org.springframework.security.access.intercept.method.aopalliance.MethodSecurityInterceptor;
|
||||
import org.springframework.security.access.intercept.method.aopalliance.MethodSecurityMetadataSourceAdvisor;
|
||||
import org.springframework.security.access.prepost.PostInvocationAdviceProvider;
|
||||
import org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter;
|
||||
import org.springframework.security.access.prepost.PrePostAnnotationSecurityMetadataSource;
|
||||
import org.springframework.security.access.vote.AffirmativeBased;
|
||||
import org.springframework.security.access.vote.AuthenticatedVoter;
|
||||
import org.springframework.security.access.vote.RoleVoter;
|
||||
@ -45,11 +54,6 @@ class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
static final String SECURED_METHOD_DEFINITION_SOURCE_CLASS = "org.springframework.security.access.annotation.SecuredMethodSecurityMetadataSource";
|
||||
static final String EXPRESSION_METHOD_DEFINITION_SOURCE_CLASS = "org.springframework.security.access.expression.method.ExpressionAnnotationMethodSecurityMetadataSource";
|
||||
static final String JSR_250_SECURITY_METHOD_DEFINITION_SOURCE_CLASS = "org.springframework.security.access.annotation.Jsr250MethodSecurityMetadataSource";
|
||||
static final String JSR_250_VOTER_CLASS = "org.springframework.security.access.annotation.Jsr250Voter";
|
||||
|
||||
/*
|
||||
* Internal Bean IDs which are only used within this class
|
||||
*/
|
||||
@ -65,7 +69,7 @@ class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
private static final String ATT_RUN_AS_MGR = "run-as-manager-ref";
|
||||
private static final String ATT_USE_JSR250 = "jsr250-annotations";
|
||||
private static final String ATT_USE_SECURED = "secured-annotations";
|
||||
private static final String ATT_USE_EXPRESSIONS = "expression-annotations";
|
||||
private static final String ATT_USE_PREPOST = "pre-post-annotations";
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
@ -75,12 +79,12 @@ class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
boolean jsr250Enabled = "enabled".equals(element.getAttribute(ATT_USE_JSR250));
|
||||
boolean useSecured = "enabled".equals(element.getAttribute(ATT_USE_SECURED));
|
||||
boolean expressionsEnabled = "enabled".equals(element.getAttribute(ATT_USE_EXPRESSIONS));
|
||||
BeanDefinition expressionVoter = null;
|
||||
boolean prePostAnnotationsEnabled = "enabled".equals(element.getAttribute(ATT_USE_PREPOST));
|
||||
BeanDefinition preInvocationVoter = null;
|
||||
|
||||
// Now create a Map<String, ConfigAttribute> for each <protect-pointcut> sub-element
|
||||
Map<String, List<ConfigAttribute>> pointcutMap = parseProtectPointcuts(parserContext,
|
||||
DomUtils.getChildElementsByTagName(element, Elements.PROTECT_POINTCUT));
|
||||
DomUtils.getChildElementsByTagName(element, PROTECT_POINTCUT));
|
||||
|
||||
if (pointcutMap.size() > 0) {
|
||||
// SEC-1016: Put the pointcut MDS first, but only add it if there are actually any pointcuts defined.
|
||||
@ -89,39 +93,70 @@ class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
registerProtectPointcutPostProcessor(parserContext, pointcutMap, mapBasedMethodSecurityMetadataSource, source);
|
||||
}
|
||||
|
||||
if (expressionsEnabled) {
|
||||
Element expressionHandlerElt = DomUtils.getChildElementByTagName(element, Elements.EXPRESSION_HANDLER);
|
||||
String expressionHandlerRef = expressionHandlerElt == null ? null : expressionHandlerElt.getAttribute("ref");
|
||||
if (prePostAnnotationsEnabled) {
|
||||
Element prePostElt = DomUtils.getChildElementByTagName(element, INVOCATION_HANDLING);
|
||||
Element expressionHandlerElt = DomUtils.getChildElementByTagName(element, EXPRESSION_HANDLER);
|
||||
|
||||
if (StringUtils.hasText(expressionHandlerRef)) {
|
||||
logger.info("Using bean '" + expressionHandlerRef + "' as method SecurityExpressionHandler implementation");
|
||||
} else {
|
||||
parserContext.getRegistry().registerBeanDefinition(EXPRESSION_HANDLER_ID, new RootBeanDefinition(DefaultMethodSecurityExpressionHandler.class));
|
||||
logger.warn("Expressions were enabled for method security but no SecurityExpressionHandler was configured. " +
|
||||
"All hasPermision() expressions will evaluate to false.");
|
||||
expressionHandlerRef = EXPRESSION_HANDLER_ID;
|
||||
if (prePostElt != null && expressionHandlerElt != null) {
|
||||
parserContext.getReaderContext().error(INVOCATION_HANDLING + " and " +
|
||||
EXPRESSION_HANDLER + " cannot be used together ", source);
|
||||
}
|
||||
BeanDefinitionBuilder expressionVoterBldr = BeanDefinitionBuilder.rootBeanDefinition(MethodExpressionVoter.class);
|
||||
BeanDefinitionBuilder afterInvocationProvider = BeanDefinitionBuilder.rootBeanDefinition(MethodExpressionAfterInvocationProvider.class);
|
||||
expressionVoterBldr.addPropertyReference("expressionHandler", expressionHandlerRef);
|
||||
expressionVoter = expressionVoterBldr.getBeanDefinition();
|
||||
// After-invocation provider to handle post-invocation filtering and authorization expression annotations.
|
||||
afterInvocationProvider.addPropertyReference("expressionHandler", expressionHandlerRef);
|
||||
ConfigUtils.getRegisteredAfterInvocationProviders(parserContext).add(afterInvocationProvider.getBeanDefinition());
|
||||
// Add the expression method definition source, which will obtain its parser from the registered expression
|
||||
// handler
|
||||
BeanDefinitionBuilder mds = BeanDefinitionBuilder.rootBeanDefinition(EXPRESSION_METHOD_DEFINITION_SOURCE_CLASS);
|
||||
mds.addConstructorArgReference(expressionHandlerRef);
|
||||
|
||||
BeanDefinitionBuilder preInvocationVoterBldr = BeanDefinitionBuilder.rootBeanDefinition(PreInvocationAuthorizationAdviceVoter.class);
|
||||
// After-invocation provider to handle post-invocation filtering and authorization expression annotations.
|
||||
BeanDefinitionBuilder afterInvocationBldr = BeanDefinitionBuilder.rootBeanDefinition(PostInvocationAdviceProvider.class);
|
||||
// The metadata source for the security interceptor
|
||||
BeanDefinitionBuilder mds = BeanDefinitionBuilder.rootBeanDefinition(PrePostAnnotationSecurityMetadataSource.class);
|
||||
|
||||
if (prePostElt != null) {
|
||||
// Customized override of expression handling system
|
||||
String attributeFactoryRef =
|
||||
DomUtils.getChildElementByTagName(prePostElt, INVOCATION_ATTRIBUTE_FACTORY).getAttribute("ref");
|
||||
String preAdviceRef =
|
||||
DomUtils.getChildElementByTagName(prePostElt, PRE_INVOCATION_ADVICE).getAttribute("ref");
|
||||
String postAdviceRef =
|
||||
DomUtils.getChildElementByTagName(prePostElt, POST_INVOCATION_ADVICE).getAttribute("ref");
|
||||
|
||||
mds.addConstructorArgReference(attributeFactoryRef);
|
||||
preInvocationVoterBldr.addConstructorArgReference(preAdviceRef);
|
||||
afterInvocationBldr.addConstructorArgReference(postAdviceRef);
|
||||
} else {
|
||||
// The default expression-based system
|
||||
String expressionHandlerRef = expressionHandlerElt == null ? null : expressionHandlerElt.getAttribute("ref");
|
||||
|
||||
if (StringUtils.hasText(expressionHandlerRef)) {
|
||||
logger.info("Using bean '" + expressionHandlerRef + "' as method ExpressionHandler implementation");
|
||||
} else {
|
||||
parserContext.getRegistry().registerBeanDefinition(EXPRESSION_HANDLER_ID, new RootBeanDefinition(DefaultMethodSecurityExpressionHandler.class));
|
||||
logger.warn("Expressions were enabled for method security but no SecurityExpressionHandler was configured. " +
|
||||
"All hasPermision() expressions will evaluate to false.");
|
||||
expressionHandlerRef = EXPRESSION_HANDLER_ID;
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder expressionPreAdviceBldr = BeanDefinitionBuilder.rootBeanDefinition(ExpressionBasedPreInvocationAdvice.class);
|
||||
expressionPreAdviceBldr.addPropertyReference("expressionHandler", expressionHandlerRef);
|
||||
preInvocationVoterBldr.addConstructorArgValue(expressionPreAdviceBldr.getBeanDefinition());
|
||||
|
||||
BeanDefinitionBuilder expressionPostAdviceBldr = BeanDefinitionBuilder.rootBeanDefinition(ExpressionBasedPostInvocationAdvice.class);
|
||||
expressionPostAdviceBldr.addConstructorArgReference(expressionHandlerRef);
|
||||
afterInvocationBldr.addConstructorArgValue(expressionPostAdviceBldr.getBeanDefinition());
|
||||
|
||||
BeanDefinitionBuilder annotationInvocationFactory = BeanDefinitionBuilder.rootBeanDefinition(ExpressionBasedAnnotationAttributeFactory.class);
|
||||
annotationInvocationFactory.addConstructorArgReference(expressionHandlerRef);
|
||||
mds.addConstructorArgValue(annotationInvocationFactory.getBeanDefinition());
|
||||
}
|
||||
|
||||
preInvocationVoter = preInvocationVoterBldr.getBeanDefinition();
|
||||
ConfigUtils.getRegisteredAfterInvocationProviders(parserContext).add(afterInvocationBldr.getBeanDefinition());
|
||||
delegates.add(mds.getBeanDefinition());
|
||||
}
|
||||
|
||||
if (useSecured) {
|
||||
delegates.add(BeanDefinitionBuilder.rootBeanDefinition(SECURED_METHOD_DEFINITION_SOURCE_CLASS).getBeanDefinition());
|
||||
delegates.add(BeanDefinitionBuilder.rootBeanDefinition(SecuredAnnotationSecurityMetadataSource.class).getBeanDefinition());
|
||||
}
|
||||
|
||||
if (jsr250Enabled) {
|
||||
delegates.add(BeanDefinitionBuilder.rootBeanDefinition(JSR_250_SECURITY_METHOD_DEFINITION_SOURCE_CLASS).getBeanDefinition());
|
||||
delegates.add(BeanDefinitionBuilder.rootBeanDefinition(Jsr250MethodSecurityMetadataSource.class).getBeanDefinition());
|
||||
}
|
||||
|
||||
registerDelegatingMethodSecurityMetadataSource(parserContext, delegates, source);
|
||||
@ -129,7 +164,7 @@ class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
String accessManagerId = element.getAttribute(ATT_ACCESS_MGR);
|
||||
|
||||
if (!StringUtils.hasText(accessManagerId)) {
|
||||
registerAccessManager(parserContext, jsr250Enabled, expressionVoter);
|
||||
registerAccessManager(parserContext, jsr250Enabled, preInvocationVoter);
|
||||
accessManagerId = ACCESS_MANAGER_ID;
|
||||
}
|
||||
|
||||
@ -161,7 +196,7 @@ class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
voters.add(new RootBeanDefinition(AuthenticatedVoter.class));
|
||||
|
||||
if (jsr250Enabled) {
|
||||
voters.add(new RootBeanDefinition(JSR_250_VOTER_CLASS, null, null));
|
||||
voters.add(new RootBeanDefinition(Jsr250Voter.class));
|
||||
}
|
||||
|
||||
accessMgrBuilder.addPropertyValue("decisionVoters", voters);
|
||||
|
@ -5,8 +5,8 @@ import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.security.authentication.dao.salt.ReflectionSaltSource;
|
||||
import org.springframework.security.authentication.dao.salt.SystemWideSaltSource;
|
||||
import org.springframework.security.authentication.dao.ReflectionSaltSource;
|
||||
import org.springframework.security.authentication.dao.SystemWideSaltSource;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
|
@ -184,10 +184,10 @@ protect.attlist &=
|
||||
|
||||
global-method-security =
|
||||
## Provides method security for all beans registered in the Spring application context. Specifically, beans will be scanned for matches with the ordered list of "protect-pointcut" sub-elements, Spring Security annotations and/or. Where there is a match, the beans will automatically be proxied and security authorization applied to the methods accordingly. If you use and enable all four sources of method security metadata (ie "protect-pointcut" declarations, expression annotations, @Secured and also JSR250 security annotations), the metadata sources will be queried in that order. In practical terms, this enables you to use XML to override method security metadata expressed in annotations. If using annotations, the order of precedence is EL-based (@PreAuthorize etc.), @Secured and finally JSR-250.
|
||||
element global-method-security {global-method-security.attlist, expression-handler?, protect-pointcut*}
|
||||
element global-method-security {global-method-security.attlist, (pre-post-annotation-handling | expression-handler)?, protect-pointcut*}
|
||||
global-method-security.attlist &=
|
||||
## Specifies whether the use of Spring Security's expression-based annotations (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) should be enabled for this application context. Defaults to "disabled".
|
||||
attribute expression-annotations {"disabled" | "enabled" }?
|
||||
## Specifies whether the use of Spring Security's pre and post invocation annotations (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) should be enabled for this application context. Defaults to "disabled".
|
||||
attribute pre-post-annotations {"disabled" | "enabled" }?
|
||||
global-method-security.attlist &=
|
||||
## Specifies whether the use of Spring Security's @Secured annotations should be enabled for this application context. Defaults to "disabled".
|
||||
attribute secured-annotations {"disabled" | "enabled" }?
|
||||
@ -201,6 +201,21 @@ global-method-security.attlist &=
|
||||
## Optional RunAsmanager implementation which will be used by the configured MethodSecurityInterceptor
|
||||
attribute run-as-manager-ref {xsd:token}?
|
||||
|
||||
pre-post-annotation-handling =
|
||||
## Allows the default expression-based mechanism for handling Spring Security's pre and post invocation annotations (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) to be replace entirely. Only applies if these annotations are enabled.
|
||||
element pre-post-annotation-handling {invocation-attribute-factory, pre-invocation-advice, post-invocation-advice}
|
||||
|
||||
invocation-attribute-factory =
|
||||
## Defines the PrePostInvocationAttributeFactory instance which is used to generate pre and post invocation metadata from the annotated methods.
|
||||
element invocation-attribute-factory {ref}
|
||||
|
||||
pre-invocation-advice =
|
||||
element pre-invocation-advice {ref}
|
||||
|
||||
post-invocation-advice =
|
||||
element post-invocation-advice {ref}
|
||||
|
||||
|
||||
expression-handler =
|
||||
## Defines the SecurityExpressionHandler instance which will be used if expression-based access-control is enabled. A default implementation (with no ACL support) will be used if not supplied.
|
||||
element expression-handler {ref}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -10,7 +10,7 @@
|
||||
<xsl:output method="xml" indent="yes"/>
|
||||
|
||||
<xsl:variable name="elts-to-inline">
|
||||
<xsl:text>,access-denied-handler,anonymous,concurrent-session-control,filter-chain,form-login,http-basic,intercept-url,logout,password-encoder,port-mappings,port-mapper,password-compare,protect,protect-pointcut,remember-me,salt-source,x509,</xsl:text>
|
||||
<xsl:text>,access-denied-handler,anonymous,concurrent-session-control,filter-chain,form-login,http-basic,intercept-url,logout,password-encoder,port-mappings,port-mapper,password-compare,protect,protect-pointcut,pre-post-annotation-handling,pre-invocation-advice,post-invocation-advice,invocation-attribute-factory,remember-me,salt-source,x509,</xsl:text>
|
||||
</xsl:variable>
|
||||
|
||||
<xsl:template match="xs:element">
|
||||
|
@ -5,6 +5,7 @@ import static org.junit.Assert.*;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.ProviderManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.authentication.dao.ReflectionSaltSource;
|
||||
import org.springframework.security.authentication.encoding.ShaPasswordEncoder;
|
||||
import org.springframework.security.config.util.InMemoryXmlApplicationContext;
|
||||
import org.springframework.security.util.FieldUtils;
|
||||
@ -111,7 +112,7 @@ public class AuthenticationProviderBeanDefinitionParserTests {
|
||||
" <b:bean id='customPasswordEncoder' " +
|
||||
"class='org.springframework.security.authentication.encoding.Md5PasswordEncoder'/>" +
|
||||
" <b:bean id='saltSource' " +
|
||||
" class='org.springframework.security.authentication.dao.salt.ReflectionSaltSource'>" +
|
||||
" class='" + ReflectionSaltSource.class.getName() +"'>" +
|
||||
" <b:property name='userPropertyToUse' value='username'/>" +
|
||||
" </b:bean>" +
|
||||
" <b:bean id='customUserService' " +
|
||||
|
@ -2,7 +2,6 @@ package org.springframework.security.config;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.security.config.ConfigTestUtils.AUTH_PROVIDER_XML;
|
||||
import static org.springframework.security.config.GlobalMethodSecurityBeanDefinitionParser.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -16,14 +15,10 @@ import org.springframework.context.support.AbstractXmlApplicationContext;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.access.annotation.BusinessService;
|
||||
import org.springframework.security.access.annotation.Jsr250MethodSecurityMetadataSource;
|
||||
import org.springframework.security.access.annotation.Jsr250Voter;
|
||||
import org.springframework.security.access.annotation.SecuredMethodSecurityMetadataSource;
|
||||
import org.springframework.security.access.expression.method.ExpressionAnnotationMethodSecurityMetadataSource;
|
||||
import org.springframework.security.access.expression.method.MethodExpressionAfterInvocationProvider;
|
||||
import org.springframework.security.access.expression.method.MethodExpressionVoter;
|
||||
import org.springframework.security.access.intercept.AfterInvocationProviderManager;
|
||||
import org.springframework.security.access.intercept.RunAsManagerImpl;
|
||||
import org.springframework.security.access.prepost.PostInvocationAdviceProvider;
|
||||
import org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter;
|
||||
import org.springframework.security.access.vote.AffirmativeBased;
|
||||
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
@ -65,14 +60,6 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
||||
target = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beanClassNamesAreCorrect() throws Exception {
|
||||
assertEquals(SecuredMethodSecurityMetadataSource.class.getName(), SECURED_METHOD_DEFINITION_SOURCE_CLASS);
|
||||
assertEquals(ExpressionAnnotationMethodSecurityMetadataSource.class.getName(), EXPRESSION_METHOD_DEFINITION_SOURCE_CLASS);
|
||||
assertEquals(Jsr250MethodSecurityMetadataSource.class.getName(), JSR_250_SECURITY_METHOD_DEFINITION_SOURCE_CLASS);
|
||||
assertEquals(Jsr250Voter.class.getName(), JSR_250_VOTER_CLASS);
|
||||
}
|
||||
|
||||
@Test(expected=AuthenticationCredentialsNotFoundException.class)
|
||||
public void targetShouldPreventProtectedMethodInvocationWithNoContext() {
|
||||
loadContext();
|
||||
@ -211,19 +198,19 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void expressionVoterAndAfterInvocationProviderUseSameExpressionHandlerInstance() throws Exception {
|
||||
setContext("<global-method-security expression-annotations='enabled'/>" + AUTH_PROVIDER_XML);
|
||||
setContext("<global-method-security pre-post-annotations='enabled'/>" + AUTH_PROVIDER_XML);
|
||||
AffirmativeBased adm = (AffirmativeBased) appContext.getBean(GlobalMethodSecurityBeanDefinitionParser.ACCESS_MANAGER_ID);
|
||||
List voters = (List) FieldUtils.getFieldValue(adm, "decisionVoters");
|
||||
MethodExpressionVoter mev = (MethodExpressionVoter) voters.get(0);
|
||||
PreInvocationAuthorizationAdviceVoter mev = (PreInvocationAuthorizationAdviceVoter) voters.get(0);
|
||||
AfterInvocationProviderManager pm = (AfterInvocationProviderManager) appContext.getBean(BeanIds.AFTER_INVOCATION_MANAGER);
|
||||
MethodExpressionAfterInvocationProvider aip = (MethodExpressionAfterInvocationProvider) pm.getProviders().get(0);
|
||||
assertTrue(FieldUtils.getFieldValue(mev, "expressionHandler") == FieldUtils.getFieldValue(aip, "expressionHandler"));
|
||||
PostInvocationAdviceProvider aip = (PostInvocationAdviceProvider) pm.getProviders().get(0);
|
||||
assertTrue(FieldUtils.getFieldValue(mev, "preAdvice.expressionHandler") == FieldUtils.getFieldValue(aip, "postAdvice.expressionHandler"));
|
||||
}
|
||||
|
||||
@Test(expected=AccessDeniedException.class)
|
||||
public void accessIsDeniedForHasRoleExpression() {
|
||||
setContext(
|
||||
"<global-method-security expression-annotations='enabled'/>" +
|
||||
"<global-method-security pre-post-annotations='enabled'/>" +
|
||||
"<b:bean id='target' class='org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl'/>" +
|
||||
AUTH_PROVIDER_XML);
|
||||
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("bob","bobspassword"));
|
||||
@ -234,7 +221,7 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
||||
@Test
|
||||
public void preAndPostFilterAnnotationsWorkWithLists() {
|
||||
setContext(
|
||||
"<global-method-security expression-annotations='enabled'/>" +
|
||||
"<global-method-security pre-post-annotations='enabled'/>" +
|
||||
"<b:bean id='target' class='org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl'/>" +
|
||||
AUTH_PROVIDER_XML);
|
||||
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("bob","bobspassword"));
|
||||
@ -253,7 +240,7 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
||||
@Test
|
||||
public void prePostFilterAnnotationWorksWithArrays() {
|
||||
setContext(
|
||||
"<global-method-security expression-annotations='enabled'/>" +
|
||||
"<global-method-security pre-post-annotations='enabled'/>" +
|
||||
"<b:bean id='target' class='org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl'/>" +
|
||||
AUTH_PROVIDER_XML);
|
||||
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("bob","bobspassword"));
|
||||
|
@ -13,9 +13,11 @@
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
|
||||
http://www.springframework.org/schema/security ../../main/resources/org/springframework/security/config/spring-security-3.0.xsd">
|
||||
|
||||
|
||||
<global-method-security run-as-manager-ref="myRunAsManager">
|
||||
<expression-handler ref="myExpressionhandler"/>
|
||||
<pre-post-annotation-handling>
|
||||
<
|
||||
</pre-post-annotation-handling>
|
||||
</global-method-security>
|
||||
|
||||
<http>
|
||||
|
@ -1,4 +1,4 @@
|
||||
package org.springframework.security.access.expression;
|
||||
package org.springframework.security.access;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@ -11,7 +11,7 @@ import org.springframework.security.core.Authentication;
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 2.5
|
||||
* @since 3.0
|
||||
*/
|
||||
public interface PermissionEvaluator {
|
||||
/**
|
@ -47,9 +47,9 @@ import java.lang.annotation.Target;
|
||||
@Inherited
|
||||
@Documented
|
||||
public @interface Secured {
|
||||
/**
|
||||
* Returns the list of security configuration attributes.
|
||||
* (i.e. ROLE_USER, ROLE_ADMIN etc.)
|
||||
/**
|
||||
* Returns the list of security configuration attributes (e.g. ROLE_USER, ROLE_ADMIN).
|
||||
*
|
||||
* @return String[] The secure method attributes
|
||||
*/
|
||||
public String[] value();
|
||||
|
@ -33,7 +33,7 @@ import org.springframework.security.access.intercept.method.AbstractFallbackMeth
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SecuredMethodSecurityMetadataSource extends AbstractFallbackMethodSecurityMetadataSource {
|
||||
public class SecuredAnnotationSecurityMetadataSource extends AbstractFallbackMethodSecurityMetadataSource {
|
||||
|
||||
protected List<ConfigAttribute> findAttributes(Class<?> clazz) {
|
||||
return processAnnotation(clazz.getAnnotation(Secured.class));
|
@ -4,7 +4,7 @@ import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.Expression;
|
||||
|
||||
public class ExpressionUtils {
|
||||
public final class ExpressionUtils {
|
||||
|
||||
public static boolean evaluateAsBoolean(Expression expr, EvaluationContext ctx) {
|
||||
try {
|
||||
|
@ -1,4 +1,4 @@
|
||||
package org.springframework.security.access.expression.support;
|
||||
package org.springframework.security.access.expression;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@ -13,7 +13,7 @@ import org.springframework.security.core.authority.AuthorityUtils;
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 2.5
|
||||
* @since 3.0
|
||||
*/
|
||||
public abstract class SecurityExpressionRoot {
|
||||
protected final Authentication authentication;
|
@ -15,7 +15,7 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 2.5
|
||||
* @since 3.0
|
||||
*/
|
||||
abstract class AbstractExpressionBasedMethodConfigAttribute implements ConfigAttribute {
|
||||
private final Expression filterExpression;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package org.springframework.security.access.expression.support;
|
||||
package org.springframework.security.access.expression.method;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
@ -14,9 +14,9 @@ import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.antlr.SpelAntlrExpressionParser;
|
||||
import org.springframework.security.access.PermissionEvaluator;
|
||||
import org.springframework.security.access.expression.ExpressionUtils;
|
||||
import org.springframework.security.access.expression.MethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.expression.PermissionEvaluator;
|
||||
import org.springframework.security.access.expression.SecurityExpressionRoot;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@ -28,7 +28,7 @@ import org.springframework.security.core.Authentication;
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 2.5
|
||||
* @since 3.0
|
||||
*/
|
||||
public class DefaultMethodSecurityExpressionHandler implements MethodSecurityExpressionHandler {
|
||||
|
@ -1,10 +1,10 @@
|
||||
package org.springframework.security.access.expression.support;
|
||||
package org.springframework.security.access.expression.method;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.security.access.expression.PermissionEvaluator;
|
||||
import org.springframework.security.access.PermissionEvaluator;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
/**
|
||||
@ -13,7 +13,7 @@ import org.springframework.security.core.Authentication;
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 2.5
|
||||
* @since 3.0
|
||||
*/
|
||||
class DenyAllPermissionEvaluator implements PermissionEvaluator {
|
||||
|
@ -0,0 +1,58 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package org.springframework.security.access.expression.method;
|
||||
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.ParseException;
|
||||
import org.springframework.security.access.prepost.PostAuthorize;
|
||||
import org.springframework.security.access.prepost.PostFilter;
|
||||
import org.springframework.security.access.prepost.PostInvocationAttribute;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.access.prepost.PreFilter;
|
||||
import org.springframework.security.access.prepost.PreInvocationAttribute;
|
||||
import org.springframework.security.access.prepost.PrePostInvocationAttributeFactory;
|
||||
|
||||
/**
|
||||
* {@link PrePostInvocationAttributeFactory} which interprets the annotation value as
|
||||
* an expression to be evaluated at runtime.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 3.0
|
||||
*/
|
||||
public class ExpressionBasedAnnotationAttributeFactory implements PrePostInvocationAttributeFactory {
|
||||
private ExpressionParser parser;
|
||||
|
||||
public ExpressionBasedAnnotationAttributeFactory(MethodSecurityExpressionHandler handler) {
|
||||
parser = handler.getExpressionParser();
|
||||
}
|
||||
|
||||
public PreInvocationAttribute createPreInvocationAttribute(PreFilter preFilter, PreAuthorize preAuthorize) {
|
||||
try {
|
||||
// TODO: Optimization of permitAll
|
||||
Expression preAuthorizeExpression = preAuthorize == null ? parser.parseExpression("permitAll") : parser.parseExpression(preAuthorize.value());
|
||||
Expression preFilterExpression = preFilter == null ? null : parser.parseExpression(preFilter.value());
|
||||
String filterObject = preFilter == null ? null : preFilter.filterTarget();
|
||||
return new PreInvocationExpressionAttribute(preFilterExpression, filterObject, preAuthorizeExpression);
|
||||
} catch (ParseException e) {
|
||||
throw new IllegalArgumentException("Failed to parse expression '" + e.getExpressionString() + "'", e);
|
||||
}
|
||||
}
|
||||
|
||||
public PostInvocationAttribute createPostInvocationAttribute(PostFilter postFilter, PostAuthorize postAuthorize) {
|
||||
try {
|
||||
Expression postAuthorizeExpression = postAuthorize == null ? null : parser.parseExpression(postAuthorize.value());
|
||||
Expression postFilterExpression = postFilter == null ? null : parser.parseExpression(postFilter.value());
|
||||
|
||||
if (postFilterExpression != null || postAuthorizeExpression != null) {
|
||||
return new PostInvocationExpressionAttribute(postFilterExpression, postAuthorizeExpression);
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
throw new IllegalArgumentException("Failed to parse expression '" + e.getExpressionString() + "'", e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package org.springframework.security.access.expression.method;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.access.expression.ExpressionUtils;
|
||||
import org.springframework.security.access.prepost.PostInvocationAttribute;
|
||||
import org.springframework.security.access.prepost.PostInvocationAuthorizationAdvice;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 3.0
|
||||
*/
|
||||
public class ExpressionBasedPostInvocationAdvice implements PostInvocationAuthorizationAdvice{
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private MethodSecurityExpressionHandler expressionHandler;
|
||||
|
||||
public ExpressionBasedPostInvocationAdvice(MethodSecurityExpressionHandler expressionHandler) {
|
||||
this.expressionHandler = expressionHandler;
|
||||
}
|
||||
|
||||
public Object after(Authentication authentication, MethodInvocation mi,
|
||||
PostInvocationAttribute postAttr, Object returnedObject) throws AccessDeniedException{
|
||||
PostInvocationExpressionAttribute pia = (PostInvocationExpressionAttribute) postAttr;
|
||||
EvaluationContext ctx = expressionHandler.createEvaluationContext(authentication, mi);
|
||||
Expression postFilter = pia.getFilterExpression();
|
||||
Expression postAuthorize = pia.getAuthorizeExpression();
|
||||
|
||||
if (postFilter != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Applying PostFilter expression " + postFilter);
|
||||
}
|
||||
|
||||
if (returnedObject != null) {
|
||||
returnedObject = expressionHandler.filter(returnedObject, postFilter, ctx);
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Return object is null, filtering will be skipped");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
expressionHandler.setReturnObject(returnedObject, ctx);
|
||||
|
||||
if (postAuthorize != null && !ExpressionUtils.evaluateAsBoolean(postAuthorize, ctx)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("PostAuthorize expression rejected access");
|
||||
}
|
||||
throw new AccessDeniedException("Access is denied");
|
||||
}
|
||||
|
||||
return returnedObject;
|
||||
}
|
||||
}
|
@ -1,68 +1,47 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package org.springframework.security.access.expression.method;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.expression.ExpressionUtils;
|
||||
import org.springframework.security.access.expression.MethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.expression.support.DefaultMethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.vote.AccessDecisionVoter;
|
||||
import org.springframework.security.access.prepost.PreInvocationAttribute;
|
||||
import org.springframework.security.access.prepost.PreInvocationAuthorizationAdvice;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
/**
|
||||
* 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',
|
||||
* to grant or deny access depending on whether the @PreAuthorize expression evaluates to 'true' or 'false',
|
||||
* respectively.
|
||||
*
|
||||
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 2.5
|
||||
* @since
|
||||
*/
|
||||
public class MethodExpressionVoter implements AccessDecisionVoter {
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
public class ExpressionBasedPreInvocationAdvice implements PreInvocationAuthorizationAdvice {
|
||||
private MethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
|
||||
|
||||
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, List<ConfigAttribute> attributes) {
|
||||
PreInvocationExpressionAttribute mace = findMethodAccessControlExpression(attributes);
|
||||
|
||||
if (mace == null) {
|
||||
// No expression based metadata, so abstain
|
||||
return ACCESS_ABSTAIN;
|
||||
}
|
||||
|
||||
MethodInvocation mi = (MethodInvocation)object;
|
||||
public boolean before(Authentication authentication, MethodInvocation mi, PreInvocationAttribute attr) {
|
||||
PreInvocationExpressionAttribute preAttr = (PreInvocationExpressionAttribute) attr;
|
||||
EvaluationContext ctx = expressionHandler.createEvaluationContext(authentication, mi);
|
||||
Expression preFilter = mace.getFilterExpression();
|
||||
Expression preAuthorize = mace.getAuthorizeExpression();
|
||||
Expression preFilter = preAttr.getFilterExpression();
|
||||
Expression preAuthorize = preAttr.getAuthorizeExpression();
|
||||
|
||||
if (preFilter != null) {
|
||||
Object filterTarget = findFilterTarget(mace.getFilterTarget(), ctx, mi);
|
||||
Object filterTarget = findFilterTarget(preAttr.getFilterTarget(), ctx, mi);
|
||||
|
||||
expressionHandler.filter(filterTarget, preFilter, ctx);
|
||||
}
|
||||
|
||||
if (preAuthorize == null) {
|
||||
return ACCESS_GRANTED;
|
||||
return true;
|
||||
}
|
||||
|
||||
return ExpressionUtils.evaluateAsBoolean(preAuthorize, ctx) ? ACCESS_GRANTED : ACCESS_DENIED;
|
||||
return ExpressionUtils.evaluateAsBoolean(preAuthorize, ctx);
|
||||
}
|
||||
|
||||
private Object findFilterTarget(String filterTargetName, EvaluationContext ctx, MethodInvocation mi) {
|
||||
@ -94,16 +73,6 @@ public class MethodExpressionVoter implements AccessDecisionVoter {
|
||||
return filterTarget;
|
||||
}
|
||||
|
||||
private PreInvocationExpressionAttribute findMethodAccessControlExpression(List<ConfigAttribute> config) {
|
||||
// Find the MethodAccessControlExpression attribute
|
||||
for (ConfigAttribute attribute : config) {
|
||||
if (attribute instanceof PreInvocationExpressionAttribute) {
|
||||
return (PreInvocationExpressionAttribute)attribute;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
|
||||
this.expressionHandler = expressionHandler;
|
@ -1,96 +0,0 @@
|
||||
package org.springframework.security.access.expression.method;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.expression.ExpressionUtils;
|
||||
import org.springframework.security.access.expression.MethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.expression.support.DefaultMethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.intercept.AfterInvocationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
/**
|
||||
* 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 MethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
|
||||
|
||||
public Object decide(Authentication authentication, Object object, List<ConfigAttribute> config, Object returnedObject)
|
||||
throws AccessDeniedException {
|
||||
|
||||
PostInvocationExpressionAttribute mca = findMethodAccessControlExpression(config);
|
||||
|
||||
if (mca == null) {
|
||||
return returnedObject;
|
||||
}
|
||||
|
||||
EvaluationContext ctx =
|
||||
expressionHandler.createEvaluationContext(authentication, (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 = expressionHandler.filter(returnedObject, postFilter, ctx);
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Return object is null, filtering will be skipped");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
expressionHandler.setReturnObject(returnedObject, ctx);
|
||||
|
||||
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 PostInvocationExpressionAttribute findMethodAccessControlExpression(List<ConfigAttribute> config) {
|
||||
// Find the MethodAccessControlExpression attribute
|
||||
for (ConfigAttribute attribute : config) {
|
||||
if (attribute instanceof PostInvocationExpressionAttribute) {
|
||||
return (PostInvocationExpressionAttribute)attribute;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
return attribute instanceof PostInvocationExpressionAttribute;
|
||||
}
|
||||
|
||||
public boolean supports(Class<?> clazz) {
|
||||
return clazz.isAssignableFrom(MethodInvocation.class);
|
||||
}
|
||||
|
||||
public void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
|
||||
this.expressionHandler = expressionHandler;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package org.springframework.security.access.expression.support;
|
||||
package org.springframework.security.access.expression.method;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@ -15,7 +15,7 @@ import org.springframework.util.ClassUtils;
|
||||
* and when they are required.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @since 2.5
|
||||
* @since 3.0
|
||||
*/
|
||||
class MethodSecurityEvaluationContext extends StandardEvaluationContext {
|
||||
private ParameterNameDiscoverer parameterNameDiscoverer;
|
@ -1,4 +1,4 @@
|
||||
package org.springframework.security.access.expression;
|
||||
package org.springframework.security.access.expression.method;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
@ -12,7 +12,7 @@ import org.springframework.security.core.Authentication;
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 2.5
|
||||
* @since 3.0
|
||||
*/
|
||||
public interface MethodSecurityExpressionHandler {
|
||||
/**
|
@ -1,8 +1,9 @@
|
||||
package org.springframework.security.access.expression.support;
|
||||
package org.springframework.security.access.expression.method;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.security.access.expression.PermissionEvaluator;
|
||||
import org.springframework.security.access.PermissionEvaluator;
|
||||
import org.springframework.security.access.expression.SecurityExpressionRoot;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
|
||||
@ -11,7 +12,7 @@ import org.springframework.security.core.Authentication;
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 2.5
|
||||
* @since 3.0
|
||||
*/
|
||||
class MethodSecurityExpressionRoot extends SecurityExpressionRoot {
|
||||
private PermissionEvaluator permissionEvaluator;
|
@ -2,8 +2,16 @@ package org.springframework.security.access.expression.method;
|
||||
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ParseException;
|
||||
import org.springframework.security.access.prepost.PostInvocationAttribute;
|
||||
|
||||
class PostInvocationExpressionAttribute extends AbstractExpressionBasedMethodConfigAttribute {
|
||||
/**
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 3.0
|
||||
*/
|
||||
class PostInvocationExpressionAttribute extends AbstractExpressionBasedMethodConfigAttribute
|
||||
implements PostInvocationAttribute {
|
||||
|
||||
PostInvocationExpressionAttribute(String filterExpression, String authorizeExpression)
|
||||
throws ParseException {
|
||||
|
@ -2,8 +2,17 @@ package org.springframework.security.access.expression.method;
|
||||
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ParseException;
|
||||
import org.springframework.security.access.prepost.PreInvocationAttribute;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 3.0
|
||||
*/
|
||||
class PreInvocationExpressionAttribute extends AbstractExpressionBasedMethodConfigAttribute
|
||||
implements PreInvocationAttribute {
|
||||
|
||||
class PreInvocationExpressionAttribute extends AbstractExpressionBasedMethodConfigAttribute {
|
||||
private final String filterTarget;
|
||||
|
||||
PreInvocationExpressionAttribute(String filterExpression, String filterTarget, String authorizeExpression)
|
||||
|
@ -0,0 +1,2 @@
|
||||
Expression handling code to support the use of Spring-EL based expressions in @PreAuthorize, @PreFilter,
|
||||
@PostAuthorizue and @PostFilter annotations. Mainly for internal framework use and liable to change.
|
@ -1,5 +0,0 @@
|
||||
package org.springframework.security.access.expression.support;
|
||||
|
||||
public class AbstractSecurityExpressionHandler {
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package org.springframework.security.access.expression.annotation;
|
||||
package org.springframework.security.access.prepost;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
@ -12,7 +12,7 @@ import java.lang.annotation.Target;
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 2.5
|
||||
* @since 3.0
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
@ -1,4 +1,4 @@
|
||||
package org.springframework.security.access.expression.annotation;
|
||||
package org.springframework.security.access.prepost;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
@ -12,7 +12,7 @@ import java.lang.annotation.Target;
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 2.5
|
||||
* @since 3.0
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
@ -0,0 +1,59 @@
|
||||
package org.springframework.security.access.prepost;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.intercept.AfterInvocationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
/**
|
||||
* <tt>AfterInvocationProvider</tt> which delegates to a {@link PostInvocationAuthorizationAdvice} instance
|
||||
* passing it the <tt>PostInvocationAttribute</tt> created from @PostAuthorize and @PostFilter annotations.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 3.0
|
||||
*/
|
||||
public class PostInvocationAdviceProvider implements AfterInvocationProvider {
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private PostInvocationAuthorizationAdvice postAdvice;
|
||||
|
||||
public PostInvocationAdviceProvider(PostInvocationAuthorizationAdvice postAdvice) {
|
||||
this.postAdvice = postAdvice;
|
||||
}
|
||||
|
||||
public Object decide(Authentication authentication, Object object, List<ConfigAttribute> config, Object returnedObject)
|
||||
throws AccessDeniedException {
|
||||
|
||||
PostInvocationAttribute pia = findPostInvocationAttribute(config);
|
||||
|
||||
if (pia == null) {
|
||||
return returnedObject;
|
||||
}
|
||||
|
||||
return postAdvice.after(authentication, (MethodInvocation)object, pia, returnedObject);
|
||||
}
|
||||
|
||||
private PostInvocationAttribute findPostInvocationAttribute(List<ConfigAttribute> config) {
|
||||
for (ConfigAttribute attribute : config) {
|
||||
if (attribute instanceof PostInvocationAttribute) {
|
||||
return (PostInvocationAttribute)attribute;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
return attribute instanceof PostInvocationAttribute;
|
||||
}
|
||||
|
||||
public boolean supports(Class<?> clazz) {
|
||||
return clazz.isAssignableFrom(MethodInvocation.class);
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package org.springframework.security.access.prepost;
|
||||
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
|
||||
/**
|
||||
* Marker interface for attributes which are created from combined @PostFilter and @PostAuthorize annotations.
|
||||
* <p>
|
||||
* Consumed by a {@link PostInvocationAuthorizationAdvice}.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 3.0
|
||||
*/
|
||||
public interface PostInvocationAttribute extends ConfigAttribute{
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package org.springframework.security.access.prepost;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
/**
|
||||
* Performs filtering and authorization logic after a method is invoked.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 3.0
|
||||
*/
|
||||
public interface PostInvocationAuthorizationAdvice {
|
||||
|
||||
Object after(Authentication authentication, MethodInvocation mi,
|
||||
PostInvocationAttribute pia, Object returnedObject) throws AccessDeniedException;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package org.springframework.security.access.expression.annotation;
|
||||
package org.springframework.security.access.prepost;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
@ -13,7 +13,7 @@ import java.lang.annotation.Target;
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 2.5
|
||||
* @since 3.0
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
@ -1,4 +1,4 @@
|
||||
package org.springframework.security.access.expression.annotation;
|
||||
package org.springframework.security.access.prepost;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
@ -23,7 +23,7 @@ import java.lang.annotation.Target;
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 2.5
|
||||
* @since 3.0
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
@ -0,0 +1,16 @@
|
||||
package org.springframework.security.access.prepost;
|
||||
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
|
||||
/**
|
||||
* Marker interface for attributes which are created from combined @PreFilter and @PreAuthorize annotations.
|
||||
* <p>
|
||||
* Consumed by a {@link PreInvocationAuthorizationAdvice}.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 3.0
|
||||
*/
|
||||
public interface PreInvocationAttribute extends ConfigAttribute{
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package org.springframework.security.access.prepost;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
/**
|
||||
* Performs argument filtering and authorization logic before a method is invoked.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 3.0
|
||||
*/
|
||||
public interface PreInvocationAuthorizationAdvice {
|
||||
|
||||
boolean before(Authentication authentication, MethodInvocation mi, PreInvocationAttribute preInvocationAttribute);
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package org.springframework.security.access.prepost;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.vote.AccessDecisionVoter;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
/**
|
||||
* Voter which performs the actions using a PreInvocationAuthorizationAdvice implementation
|
||||
* generated from @PreFilter and @PreAuthorize annotations.
|
||||
* <p>
|
||||
* In practice, if these annotations are being used, they will normally contain all the necessary
|
||||
* access control logic, so a voter-based system is not really necessary and a single <tt>AccessDecisionManager</tt>
|
||||
* which contained the same logic would suffice. However, this class fits in readily with the traditional
|
||||
* voter-based <tt>AccessDecisionManager</tt> implementations used by Spring Security.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 3.0
|
||||
*/
|
||||
public class PreInvocationAuthorizationAdviceVoter implements AccessDecisionVoter {
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private PreInvocationAuthorizationAdvice preAdvice;
|
||||
|
||||
public PreInvocationAuthorizationAdviceVoter(PreInvocationAuthorizationAdvice pre) {
|
||||
this.preAdvice = pre;
|
||||
}
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
return attribute instanceof PreInvocationAuthorizationAdvice;
|
||||
}
|
||||
|
||||
public boolean supports(Class<?> clazz) {
|
||||
return clazz.isAssignableFrom(MethodInvocation.class);
|
||||
}
|
||||
|
||||
public int vote(Authentication authentication, Object object, List<ConfigAttribute> attributes) {
|
||||
|
||||
// Find prefilter and preauth (or combined) attributes
|
||||
// if both null, abstain
|
||||
// else call advice with them
|
||||
|
||||
PreInvocationAttribute preAttr = findPreInvocationAttribute(attributes);
|
||||
|
||||
if (preAttr == null) {
|
||||
// No expression based metadata, so abstain
|
||||
return ACCESS_ABSTAIN;
|
||||
}
|
||||
|
||||
boolean allowed = preAdvice.before(authentication, (MethodInvocation)object, preAttr);
|
||||
|
||||
return allowed ? ACCESS_GRANTED : ACCESS_DENIED;
|
||||
}
|
||||
|
||||
private PreInvocationAttribute findPreInvocationAttribute(List<ConfigAttribute> config) {
|
||||
for (ConfigAttribute attribute : config) {
|
||||
if (attribute instanceof PreInvocationAttribute) {
|
||||
return (PreInvocationAttribute)attribute;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package org.springframework.security.access.expression.method;
|
||||
package org.springframework.security.access.prepost;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
@ -7,22 +7,15 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.ParseException;
|
||||
import org.springframework.expression.spel.antlr.SpelAntlrExpressionParser;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.expression.MethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.expression.annotation.PostAuthorize;
|
||||
import org.springframework.security.access.expression.annotation.PostFilter;
|
||||
import org.springframework.security.access.expression.annotation.PreAuthorize;
|
||||
import org.springframework.security.access.expression.annotation.PreFilter;
|
||||
import org.springframework.security.access.intercept.method.AbstractMethodSecurityMetadataSource;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* <tt>MethodSecurityMetadataSource</tt> which extracts metadata from the @PreFilter and @PreAuthorize annotations
|
||||
* placed on a method. The metadata is encapsulated in a {@link AbstractExpressionBasedMethodConfigAttribute} instance.
|
||||
* placed on a method. This class is merely responsible for locating the relevant annotations (if any). It delegates
|
||||
* the actual <tt>ConfigAttribute</tt> creation to its {@link PrePostInvocationAttributeFactory}, thus
|
||||
* decoupling itself from the mechanism which will enforce the annotations' behaviour.
|
||||
* <p>
|
||||
* Annotations may be specified on classes or methods, and method-specific annotations will take precedence.
|
||||
* If you use any annotation and do not specify a pre-authorization condition, then the method will be
|
||||
@ -31,25 +24,18 @@ import org.springframework.util.ClassUtils;
|
||||
* Since we are handling multiple annotations here, it's possible that we may have to combine annotations defined in
|
||||
* multiple locations for a single method - they may be defined on the method itself, or at interface or class level.
|
||||
*
|
||||
* @see MethodExpressionVoter
|
||||
* @see PreInvocationAuthorizationAdviceVoter
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @since 2.5
|
||||
* @since 3.0
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ExpressionAnnotationMethodSecurityMetadataSource extends AbstractMethodSecurityMetadataSource {
|
||||
private ExpressionParser parser;
|
||||
public class PrePostAnnotationSecurityMetadataSource extends AbstractMethodSecurityMetadataSource {
|
||||
|
||||
public ExpressionAnnotationMethodSecurityMetadataSource() {
|
||||
parser = new SpelAntlrExpressionParser();
|
||||
}
|
||||
private final PrePostInvocationAttributeFactory attributeFactory;
|
||||
|
||||
/**
|
||||
* Constructor which obtains the expression parser from the {@link MethodSecurityExpressionHandler#getExpressionParser() }
|
||||
* method on the supplied <tt>SecurityExpressionHandler</tt>.
|
||||
*/
|
||||
public ExpressionAnnotationMethodSecurityMetadataSource(MethodSecurityExpressionHandler handler) {
|
||||
parser = handler.getExpressionParser();
|
||||
public PrePostAnnotationSecurityMetadataSource(PrePostInvocationAttributeFactory attributeFactory) {
|
||||
this.attributeFactory = attributeFactory;
|
||||
}
|
||||
|
||||
public List<ConfigAttribute> getAttributes(Method method, Class<?> targetClass) {
|
||||
@ -57,7 +43,7 @@ public class ExpressionAnnotationMethodSecurityMetadataSource extends AbstractMe
|
||||
return null;
|
||||
}
|
||||
|
||||
logger.trace("Looking for expression annotations for method '" +
|
||||
logger.trace("Looking for Pre/Post annotations for method '" +
|
||||
method.getName() + "' on target class '" + targetClass + "'");
|
||||
PreFilter preFilter = findAnnotation(method, targetClass, PreFilter.class);
|
||||
PreAuthorize preAuthorize = findAnnotation(method, targetClass, PreAuthorize.class);
|
||||
@ -71,7 +57,27 @@ public class ExpressionAnnotationMethodSecurityMetadataSource extends AbstractMe
|
||||
return null;
|
||||
}
|
||||
|
||||
return createAttributeList(preFilter, preAuthorize, postFilter, postAuthorize);
|
||||
ArrayList<ConfigAttribute> attrs = new ArrayList<ConfigAttribute>();
|
||||
|
||||
PreInvocationAttribute pre = attributeFactory.createPreInvocationAttribute(preFilter, preAuthorize);
|
||||
|
||||
if (pre != null) {
|
||||
attrs.add(pre);
|
||||
}
|
||||
|
||||
PostInvocationAttribute post = attributeFactory.createPostInvocationAttribute(postFilter, postAuthorize);
|
||||
|
||||
if (post != null) {
|
||||
attrs.add(post);
|
||||
}
|
||||
|
||||
attrs.trimToSize();
|
||||
|
||||
return attrs.isEmpty() ? null : attrs;
|
||||
}
|
||||
|
||||
public Collection<ConfigAttribute> getAllConfigAttributes() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -121,40 +127,4 @@ public class ExpressionAnnotationMethodSecurityMetadataSource extends AbstractMe
|
||||
return null;
|
||||
}
|
||||
|
||||
public Collection<ConfigAttribute> getAllConfigAttributes() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<ConfigAttribute> createAttributeList(PreFilter preFilter, PreAuthorize preAuthorize,
|
||||
PostFilter postFilter, PostAuthorize postAuthorize) {
|
||||
ConfigAttribute pre = null;
|
||||
ConfigAttribute post = null;
|
||||
|
||||
// TODO: Optimization of permitAll
|
||||
try {
|
||||
Expression preAuthorizeExpression = preAuthorize == null ? parser.parseExpression("permitAll") : parser.parseExpression(preAuthorize.value());
|
||||
Expression preFilterExpression = preFilter == null ? null : parser.parseExpression(preFilter.value());
|
||||
String filterObject = preFilter == null ? null : preFilter.filterTarget();
|
||||
Expression postAuthorizeExpression = postAuthorize == null ? null : parser.parseExpression(postAuthorize.value());
|
||||
Expression postFilterExpression = postFilter == null ? null : parser.parseExpression(postFilter.value());
|
||||
|
||||
pre = new PreInvocationExpressionAttribute(preFilterExpression, filterObject, preAuthorizeExpression);
|
||||
if (postFilterExpression != null || postAuthorizeExpression != null) {
|
||||
post = new PostInvocationExpressionAttribute(postFilterExpression, postAuthorizeExpression);
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
throw new IllegalArgumentException("Failed to parse expression '" + e.getExpressionString() + "'", e);
|
||||
}
|
||||
|
||||
List<ConfigAttribute> attrs = new ArrayList<ConfigAttribute>(2);
|
||||
if (pre != null) {
|
||||
attrs.add(pre);
|
||||
}
|
||||
|
||||
if (post != null) {
|
||||
attrs.add(post);
|
||||
}
|
||||
|
||||
return attrs;
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package org.springframework.security.access.prepost;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 3.0
|
||||
*/
|
||||
public interface PrePostInvocationAttributeFactory {
|
||||
|
||||
PreInvocationAttribute createPreInvocationAttribute(PreFilter preFilter, PreAuthorize preAuthorize);
|
||||
|
||||
PostInvocationAttribute createPostInvocationAttribute(PostFilter postFilter, PostAuthorize postAuthorize);
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
<p>
|
||||
Contains the infrastructure classes for handling the @PreAuthorize, @PreFilter, @PostAuthorize and
|
||||
@PostFilter annotations.
|
||||
</p>
|
||||
Other than the annotations themselves, the classes should be regarded as for internal framework use and
|
||||
are liable to change without notice.
|
@ -13,11 +13,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.authentication.dao.salt;
|
||||
package org.springframework.security.authentication.dao;
|
||||
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.authentication.dao.SaltSource;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
|
@ -13,9 +13,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.authentication.dao.salt;
|
||||
package org.springframework.security.authentication.dao;
|
||||
|
||||
import org.springframework.security.authentication.dao.SaltSource;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
|
@ -1,5 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
Implementations that provide salts for more secure password encoding.
|
||||
</body>
|
||||
</html>
|
@ -8,7 +8,7 @@ import org.springframework.context.ApplicationEvent;
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 2.5
|
||||
* @since 3.0
|
||||
*/
|
||||
public abstract class SessionCreationEvent extends ApplicationEvent {
|
||||
|
||||
|
@ -9,7 +9,7 @@ import org.springframework.security.core.context.SecurityContext;
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 2.5
|
||||
* @since 3.0
|
||||
*/
|
||||
public abstract class SessionDestroyedEvent extends ApplicationEvent {
|
||||
|
||||
|
@ -21,7 +21,7 @@ import javax.annotation.security.RolesAllowed;
|
||||
import javax.annotation.security.PermitAll;
|
||||
|
||||
import org.springframework.security.access.annotation.Secured;
|
||||
import org.springframework.security.access.expression.annotation.PreAuthorize;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
|
||||
/**
|
||||
* @version $Id$
|
||||
|
@ -3,8 +3,9 @@ package org.springframework.security.access.annotation;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.security.access.expression.annotation.PostFilter;
|
||||
import org.springframework.security.access.expression.annotation.PreFilter;
|
||||
import org.springframework.security.access.prepost.PostFilter;
|
||||
import org.springframework.security.access.prepost.PreFilter;
|
||||
|
||||
|
||||
public class ExpressionProtectedBusinessServiceImpl implements BusinessService {
|
||||
|
||||
|
@ -6,6 +6,7 @@ import java.util.List;
|
||||
import javax.annotation.security.RolesAllowed;
|
||||
import javax.annotation.security.PermitAll;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Luke Taylor
|
||||
|
@ -23,23 +23,23 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.SecurityConfig;
|
||||
import org.springframework.security.access.annotation.SecuredMethodSecurityMetadataSource;
|
||||
import org.springframework.security.access.annotation.SecuredAnnotationSecurityMetadataSource;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Tests for {@link org.springframework.security.access.annotation.SecuredMethodSecurityMetadataSource}
|
||||
* Tests for {@link org.springframework.security.access.annotation.SecuredAnnotationSecurityMetadataSource}
|
||||
*
|
||||
* @author Mark St.Godard
|
||||
* @author Joe Scalise
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SecuredMethodDefinitionSourceTests extends TestCase {
|
||||
public class SecuredAnnotationSecurityMetadataDefinitionSourceTests extends TestCase {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private SecuredMethodSecurityMetadataSource mds = new SecuredMethodSecurityMetadataSource();;
|
||||
private Log logger = LogFactory.getLog(SecuredMethodDefinitionSourceTests.class);
|
||||
private SecuredAnnotationSecurityMetadataSource mds = new SecuredAnnotationSecurityMetadataSource();;
|
||||
private Log logger = LogFactory.getLog(SecuredAnnotationSecurityMetadataDefinitionSourceTests.class);
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
@ -11,8 +11,8 @@ import java.util.List;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.expression.method.MethodExpressionVoter;
|
||||
import org.springframework.security.access.expression.method.PreInvocationExpressionAttribute;
|
||||
import org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter;
|
||||
import org.springframework.security.access.vote.AccessDecisionVoter;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.util.SimpleMethodInvocation;
|
||||
@ -20,7 +20,8 @@ import org.springframework.security.util.SimpleMethodInvocation;
|
||||
@SuppressWarnings("unchecked")
|
||||
public class MethodExpressionVoterTests {
|
||||
private TestingAuthenticationToken joe = new TestingAuthenticationToken("joe", "joespass", "blah");
|
||||
private MethodExpressionVoter am = new MethodExpressionVoter();
|
||||
private PreInvocationAuthorizationAdviceVoter am =
|
||||
new PreInvocationAuthorizationAdviceVoter(new ExpressionBasedPreInvocationAdvice());
|
||||
|
||||
@Test
|
||||
public void hasRoleExpressionAllowsUserWithRole() throws Exception {
|
||||
|
@ -1,4 +1,4 @@
|
||||
package org.springframework.security.access.expression.support;
|
||||
package org.springframework.security.access.expression.method;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@ -9,9 +9,9 @@ import org.junit.Test;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.antlr.SpelAntlrExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.security.access.PermissionEvaluator;
|
||||
import org.springframework.security.access.expression.ExpressionUtils;
|
||||
import org.springframework.security.access.expression.PermissionEvaluator;
|
||||
import org.springframework.security.access.expression.support.MethodSecurityExpressionRoot;
|
||||
import org.springframework.security.access.expression.method.MethodSecurityExpressionRoot;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
@ -7,18 +7,22 @@ import java.util.List;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.expression.annotation.PostAuthorize;
|
||||
import org.springframework.security.access.expression.annotation.PostFilter;
|
||||
import org.springframework.security.access.expression.annotation.PreAuthorize;
|
||||
import org.springframework.security.access.expression.annotation.PreFilter;
|
||||
import org.springframework.security.access.expression.method.ExpressionAnnotationMethodSecurityMetadataSource;
|
||||
import org.springframework.security.access.expression.method.PostInvocationExpressionAttribute;
|
||||
import org.springframework.security.access.expression.method.PreInvocationExpressionAttribute;
|
||||
import org.springframework.security.access.intercept.method.MockMethodInvocation;
|
||||
import org.springframework.security.access.prepost.PostAuthorize;
|
||||
import org.springframework.security.access.prepost.PostFilter;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.access.prepost.PreFilter;
|
||||
import org.springframework.security.access.prepost.PrePostAnnotationSecurityMetadataSource;
|
||||
|
||||
|
||||
public class ExpressionAnnotationMethodDefinitionSourceTests {
|
||||
private ExpressionAnnotationMethodSecurityMetadataSource mds = new ExpressionAnnotationMethodSecurityMetadataSource();
|
||||
/**
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 3.0
|
||||
*/
|
||||
public class PrePostAnnotationSecurityMetadataSourceTests {
|
||||
private PrePostAnnotationSecurityMetadataSource mds =
|
||||
new PrePostAnnotationSecurityMetadataSource(new ExpressionBasedAnnotationAttributeFactory(new DefaultMethodSecurityExpressionHandler()));
|
||||
|
||||
private MockMethodInvocation voidImpl1;
|
||||
private MockMethodInvocation voidImpl2;
|
@ -29,7 +29,6 @@ import org.springframework.security.authentication.LockedException;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.authentication.dao.salt.SystemWideSaltSource;
|
||||
import org.springframework.security.authentication.encoding.ShaPasswordEncoder;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
@ -19,7 +19,7 @@ import static junit.framework.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.authentication.dao.salt.ReflectionSaltSource;
|
||||
import org.springframework.security.authentication.dao.ReflectionSaltSource;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
package org.springframework.security.authentication.dao.salt;
|
||||
|
||||
import org.springframework.security.authentication.dao.salt.SystemWideSaltSource;
|
||||
import org.springframework.security.authentication.dao.SystemWideSaltSource;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
|
9
core/src/test/resources/someMethod.py
Normal file
9
core/src/test/resources/someMethod.py
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
print authentication.name;
|
||||
|
||||
for authority in authentication.authorities:
|
||||
print authority
|
||||
|
||||
print "Granting access"
|
||||
|
||||
allow = 1
|
@ -17,5 +17,10 @@
|
||||
<version>2.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jython</groupId>
|
||||
<artifactId>jython</artifactId>
|
||||
<version>2.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -0,0 +1,15 @@
|
||||
package org.springframework.security.integration.python;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.access.prepost.PostInvocationAttribute;
|
||||
import org.springframework.security.access.prepost.PostInvocationAuthorizationAdvice;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
public class PythonInterpreterPostInvocationAdvice implements PostInvocationAuthorizationAdvice{
|
||||
|
||||
public Object after(Authentication authentication, MethodInvocation mi, PostInvocationAttribute pia,
|
||||
Object returnedObject) throws AccessDeniedException {
|
||||
return returnedObject;
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package org.springframework.security.integration.python;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.python.core.Py;
|
||||
import org.python.core.PyObject;
|
||||
import org.python.util.PythonInterpreter;
|
||||
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.security.access.prepost.PreInvocationAttribute;
|
||||
import org.springframework.security.access.prepost.PreInvocationAuthorizationAdvice;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
public class PythonInterpreterPreInvocationAdvice implements PreInvocationAuthorizationAdvice{
|
||||
private ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
|
||||
|
||||
public boolean before(Authentication authentication, MethodInvocation mi, PreInvocationAttribute preAttr) {
|
||||
PythonInterpreterPreInvocationAttribute pythonAttr = (PythonInterpreterPreInvocationAttribute) preAttr;
|
||||
String script = pythonAttr.getScript();
|
||||
|
||||
PythonInterpreter python = new PythonInterpreter();
|
||||
python.set("authentication", authentication);
|
||||
python.set("args", createArgumentMap(mi));
|
||||
python.set("method", mi.getMethod().getName());
|
||||
Resource scriptResource = new PathMatchingResourcePatternResolver().getResource(script);
|
||||
|
||||
try {
|
||||
python.execfile(scriptResource.getInputStream());
|
||||
} catch (IOException e) {
|
||||
throw new IllegalArgumentException("Couldn't run python script, " + script, e);
|
||||
}
|
||||
|
||||
PyObject allowed = python.get("allow");
|
||||
|
||||
if (allowed == null) {
|
||||
throw new IllegalStateException("Python script did not set the permit flag");
|
||||
}
|
||||
|
||||
return Py.tojava(allowed, Boolean.class);
|
||||
}
|
||||
|
||||
private Map<String,Object> createArgumentMap(MethodInvocation mi) {
|
||||
Object[] args = mi.getArguments();
|
||||
Object targetObject = mi.getThis();
|
||||
Method method = ClassUtils.getMostSpecificMethod(mi.getMethod(), targetObject.getClass());
|
||||
String[] paramNames = parameterNameDiscoverer.getParameterNames(method);
|
||||
|
||||
Map<String,Object> argMap = new HashMap<String,Object>();
|
||||
for(int i=0; i < args.length; i++) {
|
||||
argMap.put(paramNames[i], args[i]);
|
||||
}
|
||||
|
||||
return argMap;
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package org.springframework.security.integration.python;
|
||||
|
||||
import org.springframework.security.access.prepost.PreInvocationAttribute;
|
||||
|
||||
public class PythonInterpreterPreInvocationAttribute implements PreInvocationAttribute {
|
||||
private String script;
|
||||
|
||||
PythonInterpreterPreInvocationAttribute(String script) {
|
||||
this.script = script;
|
||||
}
|
||||
|
||||
public String getAttribute() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getScript() {
|
||||
return script;
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package org.springframework.security.integration.python;
|
||||
|
||||
import org.python.util.PythonInterpreter;
|
||||
import org.springframework.security.access.prepost.PostAuthorize;
|
||||
import org.springframework.security.access.prepost.PostFilter;
|
||||
import org.springframework.security.access.prepost.PostInvocationAttribute;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.access.prepost.PreFilter;
|
||||
import org.springframework.security.access.prepost.PreInvocationAttribute;
|
||||
import org.springframework.security.access.prepost.PrePostInvocationAttributeFactory;
|
||||
|
||||
public class PythonInterpreterPrePostInvocationAttributeFactory implements PrePostInvocationAttributeFactory{
|
||||
|
||||
public PythonInterpreterPrePostInvocationAttributeFactory() {
|
||||
PythonInterpreter.initialize(System.getProperties(), null, new String[] {});
|
||||
}
|
||||
|
||||
|
||||
public PreInvocationAttribute createPreInvocationAttribute(PreFilter preFilter, PreAuthorize preAuthorize) {
|
||||
return new PythonInterpreterPreInvocationAttribute(preAuthorize.value());
|
||||
}
|
||||
|
||||
public PostInvocationAttribute createPostInvocationAttribute(PostFilter postFilter, PostAuthorize postAuthorize) {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package org.springframework.security.integration.python;
|
||||
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
|
||||
public interface TestService {
|
||||
|
||||
@PreAuthorize("someMethod.py")
|
||||
public void someMethod();
|
||||
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package org.springframework.security.integration.python;
|
||||
|
||||
public class TestServiceImpl implements TestService {
|
||||
|
||||
public void someMethod() {
|
||||
System.out.print("Invoked someMethod()");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package org.springframework.security.integration.python;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@ContextConfiguration(locations={"/python-method-access-app-context.xml"})
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class PythonInterpreterBasedSecurityTests {
|
||||
|
||||
@Autowired
|
||||
private TestService service;
|
||||
|
||||
@Test
|
||||
public void serviceMethod() throws Exception {
|
||||
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("bob","bobspassword"));
|
||||
|
||||
// for (int i=0; i < 1000; i++) {
|
||||
service.someMethod();
|
||||
// }
|
||||
}
|
||||
}
|
32
itest/context/src/test/resources/python-method-access-app-context.xml
Executable file
32
itest/context/src/test/resources/python-method-access-app-context.xml
Executable file
@ -0,0 +1,32 @@
|
||||
<b:beans xmlns="http://www.springframework.org/schema/security"
|
||||
xmlns:b="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xmlns:security="http://www.springframework.org/schema/security"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
|
||||
|
||||
<global-method-security pre-post-annotations="enabled">
|
||||
<pre-post-annotation-handling>
|
||||
<invocation-attribute-factory ref="attributeFactory"/>
|
||||
<pre-invocation-advice ref="preAdvice"/>
|
||||
<post-invocation-advice ref="postAdvice"/>
|
||||
</pre-post-annotation-handling>
|
||||
</global-method-security>
|
||||
|
||||
<b:bean id="attributeFactory" class="org.springframework.security.integration.python.PythonInterpreterPrePostInvocationAttributeFactory"/>
|
||||
<b:bean id="preAdvice" class="org.springframework.security.integration.python.PythonInterpreterPreInvocationAdvice"/>
|
||||
<b:bean id="postAdvice" class="org.springframework.security.integration.python.PythonInterpreterPostInvocationAdvice"/>
|
||||
|
||||
<b:bean id="service" class="org.springframework.security.integration.python.TestServiceImpl"/>
|
||||
|
||||
<authentication-provider>
|
||||
<user-service>
|
||||
<user name="bob" password="bobspassword" authorities="ROLE_A,ROLE_B"/>
|
||||
</user-service>
|
||||
</authentication-provider>
|
||||
|
||||
</b:beans>
|
@ -1,30 +1,30 @@
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xmlns:security="http://www.springframework.org/schema/security"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.2.xsd">
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xmlns:security="http://www.springframework.org/schema/security"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
|
||||
|
||||
|
||||
<bean id="userRepository" class="org.springframework.security.integration.StubUserRepository"/>
|
||||
<bean id="userRepository" class="org.springframework.security.integration.StubUserRepository"/>
|
||||
|
||||
<security:authentication-provider
|
||||
user-service-ref="userDetailsService" />
|
||||
|
||||
<bean id="userDetailsService" class="org.springframework.security.integration.UserDetailsServiceImpl">
|
||||
<property name="userRepository" ref="userRepository"/>
|
||||
</bean>
|
||||
<security:authentication-provider
|
||||
user-service-ref="userDetailsService" />
|
||||
|
||||
<security:global-method-security>
|
||||
<security:protect-pointcut
|
||||
expression="execution(* org.springframework.security.integration.*Repository+.*(..))"
|
||||
access="ROLE_LOGGEDIN" />
|
||||
</security:global-method-security>
|
||||
|
||||
<aop:aspectj-autoproxy/>
|
||||
|
||||
</beans>
|
||||
<bean id="userDetailsService" class="org.springframework.security.integration.UserDetailsServiceImpl">
|
||||
<property name="userRepository" ref="userRepository"/>
|
||||
</bean>
|
||||
|
||||
<security:global-method-security>
|
||||
<security:protect-pointcut
|
||||
expression="execution(* org.springframework.security.integration.*Repository+.*(..))"
|
||||
access="ROLE_LOGGEDIN" />
|
||||
</security:global-method-security>
|
||||
|
||||
<aop:aspectj-autoproxy/>
|
||||
|
||||
</beans>
|
||||
|
@ -5,7 +5,7 @@
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.2.xsd">
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
|
||||
|
||||
<security:authentication-provider>
|
||||
<security:user-service>
|
||||
|
@ -4,7 +4,7 @@
|
||||
xmlns:sec="http://www.springframework.org/schema/security"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
|
||||
<sec:http entry-point-ref="casProcessingFilterEntryPoint">
|
||||
<sec:intercept-url pattern="/secure/extreme/**" access="ROLE_SUPERVISOR" requires-channel="https"/>
|
||||
<sec:intercept-url pattern="/secure/**" access="ROLE_USER" />
|
||||
|
@ -9,13 +9,13 @@ import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.MessageSourceAware;
|
||||
import org.springframework.context.support.MessageSourceAccessor;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.security.acls.Acl;
|
||||
import org.springframework.security.acls.AclService;
|
||||
import org.springframework.security.acls.Permission;
|
||||
import org.springframework.security.acls.domain.BasePermission;
|
||||
import org.springframework.security.acls.objectidentity.ObjectIdentityImpl;
|
||||
import org.springframework.security.acls.sid.PrincipalSid;
|
||||
import org.springframework.security.acls.sid.Sid;
|
||||
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
||||
import org.springframework.security.acls.domain.PrincipalSid;
|
||||
import org.springframework.security.acls.model.Acl;
|
||||
import org.springframework.security.acls.model.AclService;
|
||||
import org.springframework.security.acls.model.Permission;
|
||||
import org.springframework.security.acls.model.Sid;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.validation.BindingResult;
|
||||
|
@ -14,10 +14,10 @@
|
||||
*/
|
||||
package sample.contact;
|
||||
|
||||
import org.springframework.security.access.expression.annotation.PostFilter;
|
||||
import org.springframework.security.access.expression.annotation.PreAuthorize;
|
||||
import org.springframework.security.acls.Permission;
|
||||
import org.springframework.security.acls.sid.Sid;
|
||||
import org.springframework.security.access.prepost.PostFilter;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.acls.model.Permission;
|
||||
import org.springframework.security.acls.model.Sid;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -15,16 +15,16 @@
|
||||
package sample.contact;
|
||||
|
||||
|
||||
import org.springframework.security.acls.AccessControlEntry;
|
||||
import org.springframework.security.acls.MutableAcl;
|
||||
import org.springframework.security.acls.MutableAclService;
|
||||
import org.springframework.security.acls.NotFoundException;
|
||||
import org.springframework.security.acls.Permission;
|
||||
import org.springframework.security.acls.domain.BasePermission;
|
||||
import org.springframework.security.acls.objectidentity.ObjectIdentity;
|
||||
import org.springframework.security.acls.objectidentity.ObjectIdentityImpl;
|
||||
import org.springframework.security.acls.sid.PrincipalSid;
|
||||
import org.springframework.security.acls.sid.Sid;
|
||||
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
||||
import org.springframework.security.acls.domain.PrincipalSid;
|
||||
import org.springframework.security.acls.model.AccessControlEntry;
|
||||
import org.springframework.security.acls.model.MutableAcl;
|
||||
import org.springframework.security.acls.model.MutableAclService;
|
||||
import org.springframework.security.acls.model.NotFoundException;
|
||||
import org.springframework.security.acls.model.ObjectIdentity;
|
||||
import org.springframework.security.acls.model.Permission;
|
||||
import org.springframework.security.acls.model.Sid;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
@ -20,14 +20,14 @@ import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.security.acls.MutableAcl;
|
||||
import org.springframework.security.acls.MutableAclService;
|
||||
import org.springframework.security.acls.Permission;
|
||||
import org.springframework.security.acls.domain.AclImpl;
|
||||
import org.springframework.security.acls.domain.BasePermission;
|
||||
import org.springframework.security.acls.objectidentity.ObjectIdentity;
|
||||
import org.springframework.security.acls.objectidentity.ObjectIdentityImpl;
|
||||
import org.springframework.security.acls.sid.PrincipalSid;
|
||||
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
||||
import org.springframework.security.acls.domain.PrincipalSid;
|
||||
import org.springframework.security.acls.model.MutableAcl;
|
||||
import org.springframework.security.acls.model.MutableAclService;
|
||||
import org.springframework.security.acls.model.ObjectIdentity;
|
||||
import org.springframework.security.acls.model.Permission;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
|
@ -5,10 +5,10 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.expression.PermissionEvaluator;
|
||||
import org.springframework.security.acls.Permission;
|
||||
import org.springframework.security.access.PermissionEvaluator;
|
||||
import org.springframework.security.acls.AclPermissionEvaluator;
|
||||
import org.springframework.security.acls.domain.BasePermission;
|
||||
import org.springframework.security.acls.expression.AclPermissionEvaluator;
|
||||
import org.springframework.security.acls.model.Permission;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
@ -12,9 +12,9 @@
|
||||
xmlns:b="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.5.xsd">
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
|
||||
|
||||
<global-method-security expression-annotations="enabled">
|
||||
<global-method-security pre-post-annotations="enabled">
|
||||
<expression-handler ref="expressionHandler"/>
|
||||
</global-method-security>
|
||||
|
||||
@ -48,12 +48,11 @@
|
||||
<b:property name="targetUrl" value="/secure/index.htm"/>
|
||||
</b:bean>
|
||||
|
||||
<b:bean id="expressionHandler" class="org.springframework.security.access.expression.support.DefaultMethodSecurityExpressionHandler">
|
||||
<b:property name="permissionEvaluator" ref="permissionEvaluator" />
|
||||
<b:bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
|
||||
<b:property name="permissionEvaluator">
|
||||
<b:bean class="org.springframework.security.acls.AclPermissionEvaluator">
|
||||
<b:constructor-arg ref="aclService"/>
|
||||
</b:bean>
|
||||
</b:property>
|
||||
</b:bean>
|
||||
|
||||
<b:bean id="permissionEvaluator" class="org.springframework.security.acls.expression.AclPermissionEvaluator">
|
||||
<b:constructor-arg ref="aclService"/>
|
||||
</b:bean>
|
||||
|
||||
</b:beans>
|
||||
|
@ -24,7 +24,7 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.acls.domain.BasePermission;
|
||||
import org.springframework.security.acls.sid.PrincipalSid;
|
||||
import org.springframework.security.acls.domain.PrincipalSid;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
@ -11,25 +11,23 @@
|
||||
xmlns:b="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.5.xsd">
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
|
||||
|
||||
<global-method-security expression-annotations="enabled">
|
||||
<global-method-security pre-post-annotations="enabled">
|
||||
<expression-handler ref="expressionHandler"/>
|
||||
</global-method-security>
|
||||
|
||||
<!-- ======================== AUTHENTICATION ======================= -->
|
||||
|
||||
<authentication-provider>
|
||||
<password-encoder hash="md5"/>
|
||||
<jdbc-user-service data-source-ref="dataSource"/>
|
||||
</authentication-provider>
|
||||
|
||||
<b:bean id="expressionHandler" class="org.springframework.security.access.expression.support.DefaultMethodSecurityExpressionHandler">
|
||||
<b:property name="permissionEvaluator" ref="permissionEvaluator" />
|
||||
</b:bean>
|
||||
|
||||
<b:bean id="permissionEvaluator" class="org.springframework.security.acls.expression.AclPermissionEvaluator">
|
||||
<b:constructor-arg ref="aclService"/>
|
||||
<b:bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
|
||||
<b:property name="permissionEvaluator">
|
||||
<b:bean class="org.springframework.security.acls.AclPermissionEvaluator">
|
||||
<b:constructor-arg ref="aclService"/>
|
||||
</b:bean>
|
||||
</b:property>
|
||||
</b:bean>
|
||||
|
||||
</b:beans>
|
||||
|
@ -2,16 +2,16 @@ package sample.dms.secured;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.security.acls.MutableAcl;
|
||||
import org.springframework.security.acls.MutableAclService;
|
||||
import org.springframework.security.acls.NotFoundException;
|
||||
import org.springframework.security.acls.Permission;
|
||||
import org.springframework.security.acls.domain.BasePermission;
|
||||
import org.springframework.security.acls.objectidentity.ObjectIdentity;
|
||||
import org.springframework.security.acls.objectidentity.ObjectIdentityImpl;
|
||||
import org.springframework.security.acls.sid.GrantedAuthoritySid;
|
||||
import org.springframework.security.acls.sid.PrincipalSid;
|
||||
import org.springframework.security.acls.sid.Sid;
|
||||
import org.springframework.security.acls.domain.GrantedAuthoritySid;
|
||||
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
||||
import org.springframework.security.acls.domain.PrincipalSid;
|
||||
import org.springframework.security.acls.model.MutableAcl;
|
||||
import org.springframework.security.acls.model.MutableAclService;
|
||||
import org.springframework.security.acls.model.NotFoundException;
|
||||
import org.springframework.security.acls.model.ObjectIdentity;
|
||||
import org.springframework.security.acls.model.Permission;
|
||||
import org.springframework.security.acls.model.Sid;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
@ -4,12 +4,12 @@ import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.security.acls.MutableAcl;
|
||||
import org.springframework.security.acls.MutableAclService;
|
||||
import org.springframework.security.acls.domain.BasePermission;
|
||||
import org.springframework.security.acls.objectidentity.ObjectIdentity;
|
||||
import org.springframework.security.acls.objectidentity.ObjectIdentityImpl;
|
||||
import org.springframework.security.acls.sid.PrincipalSid;
|
||||
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
||||
import org.springframework.security.acls.domain.PrincipalSid;
|
||||
import org.springframework.security.acls.model.MutableAcl;
|
||||
import org.springframework.security.acls.model.MutableAclService;
|
||||
import org.springframework.security.acls.model.ObjectIdentity;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
@ -24,8 +24,8 @@
|
||||
<value>
|
||||
sample.dms.secured.SecureDocumentDao.*=PROPAGATION_REQUIRED
|
||||
sample.dms.DocumentDao.*=PROPAGATION_REQUIRED
|
||||
org.springframework.security.acls.AclService.*=PROPAGATION_REQUIRED
|
||||
org.springframework.security.acls.MutableAclService.*=PROPAGATION_REQUIRED
|
||||
org.springframework.security.acls.model.AclService.*=PROPAGATION_REQUIRED
|
||||
org.springframework.security.acls.model.MutableAclService.*=PROPAGATION_REQUIRED
|
||||
org.springframework.security.acls.jdbc.JdbcMutableAclService.*=PROPAGATION_REQUIRED
|
||||
org.springframework.security.acls.jdbc.JdbcAclService.*=PROPAGATION_REQUIRED
|
||||
</value>
|
||||
@ -114,7 +114,7 @@
|
||||
<bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter"/>
|
||||
|
||||
<!-- An access decision voter that reads ACL_ABSTRACT_ELEMENT_WRITE_PARENT configuration settings -->
|
||||
<bean id="aclAbstractElementWriteParentVoter" class="org.springframework.security.acls.vote.AclEntryVoter">
|
||||
<bean id="aclAbstractElementWriteParentVoter" class="org.springframework.security.acls.AclEntryVoter">
|
||||
<constructor-arg ref="aclService"/>
|
||||
<constructor-arg value="ACL_ABSTRACT_ELEMENT_WRITE_PARENT"/>
|
||||
<constructor-arg>
|
||||
@ -128,7 +128,7 @@
|
||||
</bean>
|
||||
|
||||
<!-- An access decision voter that reads ACL_ABSTRACT_ELEMENT_WRITE configuration settings -->
|
||||
<bean id="aclAbstractElementWriteVoter" class="org.springframework.security.acls.vote.AclEntryVoter">
|
||||
<bean id="aclAbstractElementWriteVoter" class="org.springframework.security.acls.AclEntryVoter">
|
||||
<constructor-arg ref="aclService"/>
|
||||
<constructor-arg value="ACL_ABSTRACT_ELEMENT_WRITE"/>
|
||||
<constructor-arg>
|
||||
|
@ -1,6 +1,6 @@
|
||||
package bigbank;
|
||||
|
||||
import org.springframework.security.access.expression.annotation.PreAuthorize;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
|
||||
|
||||
public interface BankService {
|
||||
|
@ -10,9 +10,9 @@
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.5.xsd">
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
|
||||
|
||||
<global-method-security expression-annotations="enabled">
|
||||
<global-method-security prepost-annotations="enabled">
|
||||
<!-- AspectJ pointcut expression that locates our "post" method and applies security that way
|
||||
<protect-pointcut expression="execution(* bigbank.*Service.post*(..))" access="ROLE_TELLER"/>
|
||||
-->
|
||||
|
Loading…
x
Reference in New Issue
Block a user