From f7f6798f71648ed680638898dfcc59e10ad3d70d Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Mon, 30 Apr 2018 11:41:43 -0500 Subject: [PATCH] DefaultWebSecurityExpressionHandler uses PermissionEvaluator Bean The default instance of DefaultWebSecurityExpressionHandler uses the PermissionEvaluator Bean by default. Fixes: gh-5272 --- .../annotation/web/builders/WebSecurity.java | 6 ++ .../WebSecurityConfigurationTests.java | 70 +++++++++++++++---- 2 files changed, 64 insertions(+), 12 deletions(-) diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java index d0f69bf929..c37b3f24f0 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java @@ -29,6 +29,7 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.http.HttpMethod; +import org.springframework.security.access.PermissionEvaluator; import org.springframework.security.access.expression.SecurityExpressionHandler; import org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder; import org.springframework.security.config.annotation.ObjectPostProcessor; @@ -382,6 +383,11 @@ public final class WebSecurity extends throws BeansException { this.defaultWebSecurityExpressionHandler .setApplicationContext(applicationContext); + try { + this.defaultWebSecurityExpressionHandler.setPermissionEvaluator(applicationContext.getBean( + PermissionEvaluator.class)); + } catch(NoSuchBeanDefinitionException e) {} + this.ignoredRequestRegistry = new IgnoredRequestConfigurer(applicationContext); try { this.httpFirewall = applicationContext.getBean(HttpFirewall.class); diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java index 44b7fe94d2..5fc87dfe5d 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java @@ -15,6 +15,19 @@ */ package org.springframework.security.config.annotation.web.configuration; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.io.Serializable; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.List; + import org.junit.Rule; import org.junit.Test; import org.springframework.beans.factory.BeanCreationException; @@ -23,15 +36,24 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.core.annotation.Order; +import org.springframework.expression.EvaluationContext; +import org.springframework.expression.Expression; import org.springframework.expression.ExpressionParser; +import org.springframework.mock.web.MockFilterChain; import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.security.access.PermissionEvaluator; +import org.springframework.security.access.expression.AbstractSecurityExpressionHandler; import org.springframework.security.access.expression.SecurityExpressionHandler; +import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.test.SpringTestRule; import org.springframework.security.config.users.AuthenticationTestConfiguration; +import org.springframework.security.core.Authentication; import org.springframework.security.web.FilterChainProxy; +import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator; import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator; @@ -41,18 +63,6 @@ import org.springframework.util.ClassUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - /** * Tests for {@link WebSecurityConfiguration}. * @@ -260,6 +270,42 @@ public class WebSecurityConfigurationTests { } } + @Test + public void securityExpressionHandlerWhenPermissionEvaluatorBeanThenPermissionEvaluatorUsed() throws Exception { + this.spring.register(WebSecurityExpressionHandlerPermissionEvaluatorBeanConfig.class).autowire(); + TestingAuthenticationToken authentication = new TestingAuthenticationToken("user", "notused"); + FilterInvocation invocation = new FilterInvocation(new MockHttpServletRequest(), new MockHttpServletResponse(), new MockFilterChain()); + + AbstractSecurityExpressionHandler handler = this.spring.getContext().getBean(AbstractSecurityExpressionHandler.class); + EvaluationContext evaluationContext = handler.createEvaluationContext(authentication, invocation); + Expression expression = handler.getExpressionParser() + .parseExpression("hasPermission(#study,'DELETE')"); + boolean granted = expression.getValue(evaluationContext, Boolean.class); + assertThat(granted).isTrue(); + } + + @EnableWebSecurity + static class WebSecurityExpressionHandlerPermissionEvaluatorBeanConfig extends WebSecurityConfigurerAdapter { + static final PermissionEvaluator PERMIT_ALL_PERMISSION_EVALUATOR = new PermissionEvaluator() { + @Override + public boolean hasPermission(Authentication authentication, + Object targetDomainObject, Object permission) { + return true; + } + + @Override + public boolean hasPermission(Authentication authentication, + Serializable targetId, String targetType, Object permission) { + return true; + } + }; + + @Bean + public PermissionEvaluator permissionEvaluator() { + return PERMIT_ALL_PERMISSION_EVALUATOR; + } + } + @Test public void loadConfigWhenDefaultWebInvocationPrivilegeEvaluatorThenDefaultIsRegistered() throws Exception { this.spring.register(WebInvocationPrivilegeEvaluatorDefaultsConfig.class).autowire();