SEC-1294: Enable access to beans from ApplicationContext in EL expressions.
ExpressionHandlers are now ApplicationContextAware and set the app context on the SecurityExpressionRoot. A custom PropertyAccessor resolves the properties against the root by looking them up in the app context.
This commit is contained in:
+14
-3
@@ -1,10 +1,14 @@
|
||||
package org.springframework.security.web.access.expression;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.security.access.expression.SecurityExpressionRoot;
|
||||
import org.springframework.security.access.expression.SecurityExpressionRootPropertyAccessor;
|
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
|
||||
@@ -18,22 +22,25 @@ import org.springframework.security.web.FilterInvocation;
|
||||
* @author Luke Taylor
|
||||
* @since 3.0
|
||||
*/
|
||||
public class DefaultWebSecurityExpressionHandler implements WebSecurityExpressionHandler {
|
||||
public class DefaultWebSecurityExpressionHandler implements WebSecurityExpressionHandler, ApplicationContextAware {
|
||||
|
||||
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
|
||||
private ExpressionParser expressionParser = new SpelExpressionParser();
|
||||
private final SecurityExpressionRootPropertyAccessor sxrpa = new SecurityExpressionRootPropertyAccessor();
|
||||
private RoleHierarchy roleHierarchy;
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
public ExpressionParser getExpressionParser() {
|
||||
return expressionParser;
|
||||
}
|
||||
|
||||
public EvaluationContext createEvaluationContext(Authentication authentication, FilterInvocation fi) {
|
||||
StandardEvaluationContext ctx = new StandardEvaluationContext();
|
||||
SecurityExpressionRoot root = new WebSecurityExpressionRoot(authentication, fi);
|
||||
root.setTrustResolver(trustResolver);
|
||||
root.setRoleHierarchy(roleHierarchy);
|
||||
ctx.setRootObject(root);
|
||||
root.setApplicationContext(applicationContext);
|
||||
StandardEvaluationContext ctx = new StandardEvaluationContext(root);
|
||||
ctx.addPropertyAccessor(sxrpa);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
@@ -41,4 +48,8 @@ public class DefaultWebSecurityExpressionHandler implements WebSecurityExpressio
|
||||
public void setRoleHierarchy(RoleHierarchy roleHierarchy) {
|
||||
this.roleHierarchy = roleHierarchy;
|
||||
}
|
||||
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
}
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package org.springframework.security.web.access.expression;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.security.access.SecurityConfig;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.FilterInvocation;
|
||||
|
||||
public class DefaultWebSecurityExpressionHandlerTests {
|
||||
|
||||
@Test
|
||||
public void expressionPropertiesAreResolvedAgainsAppContextBeans() throws Exception {
|
||||
DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();
|
||||
StaticApplicationContext appContext = new StaticApplicationContext();
|
||||
RootBeanDefinition bean = new RootBeanDefinition(SecurityConfig.class);
|
||||
bean.getConstructorArgumentValues().addGenericArgumentValue("ROLE_A");
|
||||
appContext.registerBeanDefinition("role", bean);
|
||||
handler.setApplicationContext(appContext);
|
||||
|
||||
EvaluationContext ctx = handler.createEvaluationContext(mock(Authentication.class), mock(FilterInvocation.class));
|
||||
ExpressionParser parser = handler.getExpressionParser();
|
||||
assertTrue(parser.parseExpression("role.getAttribute() == 'ROLE_A'").getValue(ctx, Boolean.class));
|
||||
assertTrue(parser.parseExpression("role.attribute == 'ROLE_A'").getValue(ctx, Boolean.class));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user