2
0
Эх сурвалжийг харах

SEC-1749: Add support for PageContext lookup of objects and use of PermissionEvaluator when using web access expressions.

Luke Taylor 14 жил өмнө
parent
commit
63f160dc72

+ 10 - 0
core/src/main/java/org/springframework/security/access/expression/AbstractSecurityExpressionHandler.java

@@ -8,6 +8,7 @@ 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.PermissionEvaluator;
 import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
 import org.springframework.security.authentication.AuthenticationTrustResolver;
 import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
@@ -25,6 +26,7 @@ public abstract class AbstractSecurityExpressionHandler<T> implements SecurityEx
     private final ExpressionParser expressionParser = new SpelExpressionParser();
     private BeanResolver br;
     private RoleHierarchy roleHierarchy;
+    private PermissionEvaluator permissionEvaluator = new DenyAllPermissionEvaluator();
 
     public final ExpressionParser getExpressionParser() {
         return expressionParser;
@@ -77,6 +79,14 @@ public abstract class AbstractSecurityExpressionHandler<T> implements SecurityEx
         this.roleHierarchy = roleHierarchy;
     }
 
+    protected PermissionEvaluator getPermissionEvaluator() {
+        return permissionEvaluator;
+    }
+
+    public void setPermissionEvaluator(PermissionEvaluator permissionEvaluator) {
+        this.permissionEvaluator = permissionEvaluator;
+    }
+
     public void setApplicationContext(ApplicationContext applicationContext) {
         br = new BeanFactoryResolver(applicationContext);
     }

+ 2 - 2
core/src/main/java/org/springframework/security/access/expression/method/DenyAllPermissionEvaluator.java → core/src/main/java/org/springframework/security/access/expression/DenyAllPermissionEvaluator.java

@@ -1,4 +1,4 @@
-package org.springframework.security.access.expression.method;
+package org.springframework.security.access.expression;
 
 import java.io.Serializable;
 
@@ -14,7 +14,7 @@ import org.springframework.security.core.Authentication;
  * @author Luke Taylor
  * @since 3.0
  */
-class DenyAllPermissionEvaluator implements PermissionEvaluator {
+public class DenyAllPermissionEvaluator implements PermissionEvaluator {
 
     private final Log logger = LogFactory.getLog(getClass());
 

+ 2 - 6
core/src/main/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandler.java

@@ -14,6 +14,7 @@ import org.springframework.expression.spel.support.StandardEvaluationContext;
 import org.springframework.security.access.PermissionCacheOptimizer;
 import org.springframework.security.access.PermissionEvaluator;
 import org.springframework.security.access.expression.AbstractSecurityExpressionHandler;
+import org.springframework.security.access.expression.DenyAllPermissionEvaluator;
 import org.springframework.security.access.expression.ExpressionUtils;
 import org.springframework.security.access.expression.SecurityExpressionRoot;
 import org.springframework.security.core.Authentication;
@@ -31,7 +32,6 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
     protected final Log logger = LogFactory.getLog(getClass());
 
     private ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
-    private PermissionEvaluator permissionEvaluator = new DenyAllPermissionEvaluator();
     private PermissionCacheOptimizer permissionCacheOptimizer = null;
 
     public DefaultMethodSecurityExpressionHandler() {
@@ -48,7 +48,7 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
     protected SecurityExpressionRoot createSecurityExpressionRoot(Authentication authentication, MethodInvocation invocation) {
         MethodSecurityExpressionRoot root = new MethodSecurityExpressionRoot(authentication);
         root.setThis(invocation.getThis());
-        root.setPermissionEvaluator(permissionEvaluator);
+        root.setPermissionEvaluator(getPermissionEvaluator());
 
         return root;
     }
@@ -140,10 +140,6 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
         this.parameterNameDiscoverer = parameterNameDiscoverer;
     }
 
-    public void setPermissionEvaluator(PermissionEvaluator permissionEvaluator) {
-        this.permissionEvaluator = permissionEvaluator;
-    }
-
     public void setPermissionCacheOptimizer(PermissionCacheOptimizer permissionCacheOptimizer) {
         this.permissionCacheOptimizer = permissionCacheOptimizer;
     }

+ 0 - 13
core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityEvaluationContext.java

@@ -7,8 +7,6 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.springframework.aop.framework.AopProxyUtils;
 import org.springframework.aop.support.AopUtils;
-import org.springframework.beans.factory.NoSuchBeanDefinitionException;
-import org.springframework.context.ApplicationContext;
 import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
 import org.springframework.core.ParameterNameDiscoverer;
 import org.springframework.expression.spel.support.StandardEvaluationContext;
@@ -27,7 +25,6 @@ class MethodSecurityEvaluationContext extends StandardEvaluationContext {
 
     private ParameterNameDiscoverer parameterNameDiscoverer;
     private final MethodInvocation mi;
-    private ApplicationContext appContext;
     private boolean argumentsAdded;
 
     /**
@@ -64,16 +61,6 @@ class MethodSecurityEvaluationContext extends StandardEvaluationContext {
             return variable;
         }
 
-        if (appContext != null) {
-            try {
-                super.setVariable(name, appContext.getBean(name));
-
-                return super.lookupVariable(name);
-            } catch (NoSuchBeanDefinitionException e) {
-                logger.debug("Bean lookup for variable '" + name + "' failed");
-            }
-        }
-
         return null;
     }
 

+ 10 - 3
taglibs/src/main/java/org/springframework/security/taglibs/authz/AbstractAuthorizeTag.java

@@ -31,6 +31,7 @@ import javax.servlet.http.HttpServletRequest;
 
 import org.springframework.context.ApplicationContext;
 import org.springframework.core.GenericTypeResolver;
+import org.springframework.expression.EvaluationContext;
 import org.springframework.expression.Expression;
 import org.springframework.expression.ParseException;
 import org.springframework.security.access.expression.ExpressionUtils;
@@ -161,8 +162,7 @@ public abstract class AbstractAuthorizeTag {
      * @throws IOException
      */
     public boolean authorizeUsingAccessExpression() throws IOException {
-        Authentication currentUser = SecurityContextHolder.getContext().getAuthentication();
-        if (currentUser == null) {
+        if (SecurityContextHolder.getContext().getAuthentication() == null) {
             return false;
         }
 
@@ -178,13 +178,20 @@ public abstract class AbstractAuthorizeTag {
             throw ioException;
         }
 
+        return ExpressionUtils.evaluateAsBoolean(accessExpression, createExpressionEvaluationContext(handler));
+    }
+
+    /**
+     * Allows the {@code EvaluationContext} to be customized for variable lookup etc.
+     */
+    protected EvaluationContext createExpressionEvaluationContext(SecurityExpressionHandler<FilterInvocation> handler) {
         FilterInvocation f = new FilterInvocation(getRequest(), getResponse(), new FilterChain() {
             public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
                 throw new UnsupportedOperationException();
             }
         });
 
-        return ExpressionUtils.evaluateAsBoolean(accessExpression, handler.createEvaluationContext(currentUser, f));
+        return handler.createEvaluationContext(SecurityContextHolder.getContext().getAuthentication(), f);
     }
 
     /**

+ 76 - 0
taglibs/src/main/java/org/springframework/security/taglibs/authz/JspAuthorizeTag.java

@@ -1,6 +1,7 @@
 package org.springframework.security.taglibs.authz;
 
 import java.io.IOException;
+import java.util.*;
 
 import javax.servlet.ServletContext;
 import javax.servlet.ServletRequest;
@@ -9,7 +10,19 @@ import javax.servlet.jsp.JspException;
 import javax.servlet.jsp.PageContext;
 import javax.servlet.jsp.tagext.Tag;
 
+import org.springframework.expression.BeanResolver;
+import org.springframework.expression.ConstructorResolver;
+import org.springframework.expression.EvaluationContext;
+import org.springframework.expression.MethodResolver;
+import org.springframework.expression.OperatorOverloader;
+import org.springframework.expression.PropertyAccessor;
+import org.springframework.expression.TypeComparator;
+import org.springframework.expression.TypeConverter;
+import org.springframework.expression.TypeLocator;
+import org.springframework.expression.TypedValue;
+import org.springframework.security.access.expression.SecurityExpressionHandler;
 import org.springframework.security.taglibs.TagLibConfig;
+import org.springframework.security.web.FilterInvocation;
 import org.springframework.web.util.ExpressionEvaluationUtils;
 
 /**
@@ -60,6 +73,11 @@ public class JspAuthorizeTag extends AbstractAuthorizeTag implements Tag {
         }
     }
 
+    @Override
+    protected EvaluationContext createExpressionEvaluationContext(SecurityExpressionHandler<FilterInvocation> handler) {
+        return new PageContextVariableLookupEvaluationContext(super.createExpressionEvaluationContext(handler));
+    }
+
     /**
      * Default processing of the end tag returning EVAL_PAGE.
      *
@@ -126,4 +144,62 @@ public class JspAuthorizeTag extends AbstractAuthorizeTag implements Tag {
         return pageContext.getServletContext();
     }
 
+    private final class PageContextVariableLookupEvaluationContext implements EvaluationContext {
+
+        private EvaluationContext delegate;
+
+        private PageContextVariableLookupEvaluationContext(EvaluationContext delegate) {
+            this.delegate = delegate;
+        }
+
+        public TypedValue getRootObject() {
+            return delegate.getRootObject();
+        }
+
+        public List<ConstructorResolver> getConstructorResolvers() {
+            return delegate.getConstructorResolvers();
+        }
+
+        public List<MethodResolver> getMethodResolvers() {
+            return delegate.getMethodResolvers();
+        }
+
+        public List<PropertyAccessor> getPropertyAccessors() {
+            return delegate.getPropertyAccessors();
+        }
+
+        public TypeLocator getTypeLocator() {
+            return delegate.getTypeLocator();
+        }
+
+        public TypeConverter getTypeConverter() {
+            return delegate.getTypeConverter();
+        }
+
+        public TypeComparator getTypeComparator() {
+            return delegate.getTypeComparator();
+        }
+
+        public OperatorOverloader getOperatorOverloader() {
+            return delegate.getOperatorOverloader();
+        }
+
+        public BeanResolver getBeanResolver() {
+            return delegate.getBeanResolver();
+        }
+
+        public void setVariable(String name, Object value) {
+            delegate.setVariable(name, value);
+        }
+
+        public Object lookupVariable(String name) {
+            Object result = delegate.lookupVariable(name);
+
+            if (result == null) {
+                result = pageContext.findAttribute(name);
+            }
+            return result;
+        }
+    }
+
 }

+ 9 - 1
taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthorizeTagTests.java

@@ -44,6 +44,7 @@ public class AuthorizeTagTests {
     //~ Instance fields ================================================================================================
 
     private JspAuthorizeTag authorizeTag;
+    private MockHttpServletRequest request = new MockHttpServletRequest();
     private final TestingAuthenticationToken currentUser = new TestingAuthenticationToken("abc", "123", "ROLE SUPERVISOR", "ROLE_TELLER");
 
     //~ Methods ========================================================================================================
@@ -57,7 +58,7 @@ public class AuthorizeTagTests {
         MockServletContext servletCtx = new MockServletContext();
         servletCtx.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ctx);
         authorizeTag = new JspAuthorizeTag();
-        authorizeTag.setPageContext(new MockPageContext(servletCtx, new MockHttpServletRequest(), new MockHttpServletResponse()));
+        authorizeTag.setPageContext(new MockPageContext(servletCtx, request, new MockHttpServletResponse()));
     }
 
     @After
@@ -86,6 +87,13 @@ public class AuthorizeTagTests {
         assertEquals(Tag.EVAL_BODY_INCLUDE, authorizeTag.doStartTag());
     }
 
+    @Test
+    public void requestAttributeIsResolvedAsElVariable() throws JspException {
+        request.setAttribute("blah", "blah");
+        authorizeTag.setAccess("#blah == 'blah'");
+        assertEquals(Tag.EVAL_BODY_INCLUDE, authorizeTag.doStartTag());
+    }
+
     // url attribute tests
     @Test
     public void skipsBodyWithUrlSetIfNoAuthenticationPresent() throws Exception {

+ 3 - 1
web/src/main/java/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandler.java

@@ -14,6 +14,8 @@ public class DefaultWebSecurityExpressionHandler extends AbstractSecurityExpress
 
     @Override
     protected SecurityExpressionRoot createSecurityExpressionRoot(Authentication authentication, FilterInvocation fi) {
-        return new WebSecurityExpressionRoot(authentication, fi);
+        WebSecurityExpressionRoot root = new WebSecurityExpressionRoot(authentication, fi);
+        root.setPermissionEvaluator(getPermissionEvaluator());
+        return root;
     }
 }