Browse Source

SEC-2303: WebSecurity sets the Bean resolver

Rob Winch 12 years ago
parent
commit
5f10d84bf5

+ 13 - 2
config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java

@@ -23,6 +23,9 @@ import javax.servlet.http.HttpServletRequest;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
 import org.springframework.security.access.expression.SecurityExpressionHandler;
 import org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder;
 import org.springframework.security.config.annotation.SecurityBuilder;
@@ -68,7 +71,7 @@ import org.springframework.web.filter.DelegatingFilterProxy;
  * @since 3.2
  */
 public final class WebSecurity extends
-        AbstractConfiguredSecurityBuilder<Filter, WebSecurity> implements SecurityBuilder<Filter> {
+        AbstractConfiguredSecurityBuilder<Filter, WebSecurity> implements SecurityBuilder<Filter>, ApplicationContextAware {
     private final Log logger = LogFactory.getLog(getClass());
 
     private final List<RequestMatcher> ignoredRequests = new ArrayList<RequestMatcher>();
@@ -87,7 +90,10 @@ public final class WebSecurity extends
 
     private WebInvocationPrivilegeEvaluator privilegeEvaluator;
 
-    private SecurityExpressionHandler<FilterInvocation> expressionHandler = new DefaultWebSecurityExpressionHandler();
+    private DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();
+
+    private SecurityExpressionHandler<FilterInvocation> expressionHandler = defaultWebSecurityExpressionHandler;
+
 
     private Runnable postBuildAction = new Runnable() {
         public void run() {}
@@ -325,4 +331,9 @@ public final class WebSecurity extends
 
         private IgnoredRequestConfigurer(){}
     }
+
+    public void setApplicationContext(ApplicationContext applicationContext)
+            throws BeansException {
+        defaultWebSecurityExpressionHandler.setApplicationContext(applicationContext);
+    }
 }

+ 6 - 0
config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.java

@@ -34,6 +34,7 @@ import org.springframework.core.annotation.AnnotationUtils;
 import org.springframework.core.annotation.Order;
 import org.springframework.core.type.AnnotationMetadata;
 import org.springframework.security.access.expression.SecurityExpressionHandler;
+import org.springframework.security.config.annotation.ObjectPostProcessor;
 import org.springframework.security.config.annotation.SecurityConfigurer;
 import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
 import org.springframework.security.config.annotation.web.builders.WebSecurity;
@@ -184,4 +185,9 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa
     public void setBeanClassLoader(ClassLoader classLoader) {
         this.beanClassLoader = classLoader;
     }
+
+    @Autowired
+    public void setObjectPostProcessor(ObjectPostProcessor<Object> objectPostProcessor) {
+        objectPostProcessor.postProcess(webSecurity);
+    }
 }

+ 1 - 1
config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java

@@ -151,7 +151,7 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
             if(trustResolver != null) {
                 defaultHandler.setTrustResolver(trustResolver);
             }
-            expressionHandler = defaultHandler;
+            expressionHandler = postProcess(defaultHandler);
         }
 
         return expressionHandler;

+ 56 - 0
config/src/test/groovy/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.groovy

@@ -24,6 +24,9 @@ import org.springframework.context.ApplicationListener;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration
 import org.springframework.core.annotation.Order
+import org.springframework.expression.ExpressionParser;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.security.access.expression.SecurityExpressionHandler;
 import org.springframework.security.authentication.AuthenticationManager
 import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
 import org.springframework.security.config.annotation.BaseSpringSpec
@@ -36,7 +39,9 @@ import org.springframework.security.web.access.DefaultWebInvocationPrivilegeEval
 import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
 import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
 import org.springframework.security.web.access.expression.WebSecurityExpressionHandler;
+import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
 import org.springframework.security.web.util.AnyRequestMatcher
+import org.springframework.test.util.ReflectionTestUtils;
 
 /**
  * @author Rob Winch
@@ -197,11 +202,13 @@ class WebSecurityConfigurationTests extends BaseSpringSpec {
     def "Override webSecurityExpressionHandler"() {
         setup:
             WebSecurityExpressionHandler expressionHandler = Mock()
+            ExpressionParser parser = Mock()
             WebSecurityExpressionHandlerConfig.EH = expressionHandler
         when:
             loadConfig(WebSecurityExpressionHandlerConfig)
         then:
             context.getBean(WebSecurityExpressionHandler) == expressionHandler
+            1 * expressionHandler.getExpressionParser() >> parser
     }
 
     @EnableWebSecurity
@@ -215,6 +222,13 @@ class WebSecurityConfigurationTests extends BaseSpringSpec {
             web
                 .expressionHandler(EH)
         }
+        @Override
+        protected void configure(HttpSecurity http) throws Exception {
+            http
+                .authorizeRequests()
+                    .expressionHandler(EH)
+                    .anyRequest().authenticated()
+        }
     }
 
     def "#138 webSecurityExpressionHandler defaults"() {
@@ -257,4 +271,46 @@ class WebSecurityConfigurationTests extends BaseSpringSpec {
                     .anyRequest().authenticated()
         }
     }
+
+    def "SEC-2303: DefaultExpressionHandler has bean resolver set"() {
+        when:
+            loadConfig(DefaultExpressionHandlerSetsBeanResolverConfig)
+        then: "the exposed bean has a BeanResolver set"
+            ReflectionTestUtils.getField(context.getBean(SecurityExpressionHandler),"br")
+        when:
+            springSecurityFilterChain.doFilter(request, response, chain)
+        then: "we can use the BeanResolver with a grant"
+            noExceptionThrown()
+        when: "we can use the Beanresolver with a deny"
+            springSecurityFilterChain.doFilter(new MockHttpServletRequest(method:'POST'), response, chain)
+        then:
+            noExceptionThrown()
+    }
+
+    @EnableWebSecurity
+    @Configuration
+    static class DefaultExpressionHandlerSetsBeanResolverConfig extends WebSecurityConfigurerAdapter {
+
+        @Override
+        protected void configure(HttpSecurity http) throws Exception {
+            http
+                .authorizeRequests()
+                    .anyRequest().access("request.method == 'GET' ? @b.grant() : @b.deny()")
+        }
+
+        @Bean
+        public MyBean b() {
+            new MyBean()
+        }
+
+        static class MyBean {
+            boolean deny() {
+                false
+            }
+
+            boolean grant() {
+                true
+            }
+        }
+    }
 }