From eb90857d6ea4f477115520fb2a4fd3ca756a954e Mon Sep 17 00:00:00 2001 From: Evgeniy Cheban Date: Thu, 4 Jun 2020 12:53:00 +0300 Subject: [PATCH] DefaultWebSecurityExpressionHandler uses RoleHierarchy bean Fixes gh-7059 --- .../annotation/web/builders/WebSecurity.java | 9 +++++- .../WebSecurityConfigurationTests.java | 30 ++++++++++++++++++- 2 files changed, 37 insertions(+), 2 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 e08b1eae97..47776bacaa 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,6 +31,7 @@ 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.access.hierarchicalroles.RoleHierarchy; import org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder; import org.springframework.security.config.annotation.ObjectPostProcessor; import org.springframework.security.config.annotation.SecurityBuilder; @@ -74,6 +75,7 @@ import org.springframework.web.filter.DelegatingFilterProxy; * @see WebSecurityConfiguration * * @author Rob Winch + * @author Evgeniy Cheban * @since 3.2 */ public final class WebSecurity extends @@ -383,6 +385,11 @@ public final class WebSecurity extends throws BeansException { this.defaultWebSecurityExpressionHandler .setApplicationContext(applicationContext); + + try { + this.defaultWebSecurityExpressionHandler.setRoleHierarchy(applicationContext.getBean(RoleHierarchy.class)); + } catch (NoSuchBeanDefinitionException e) {} + try { this.defaultWebSecurityExpressionHandler.setPermissionEvaluator(applicationContext.getBean( PermissionEvaluator.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 c27fca6201..c1d7d47b9f 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,6 +32,8 @@ 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.access.hierarchicalroles.RoleHierarchy; +import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl; import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication; @@ -69,6 +71,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * * @author Rob Winch * @author Joe Grandja + * @author Evgeniy Cheban */ public class WebSecurityConfigurationTests { @Rule @@ -290,6 +293,31 @@ public class WebSecurityConfigurationTests { } } + @Test + public void securityExpressionHandlerWhenRoleHierarchyBeanThenRoleHierarchyUsed() { + this.spring.register(WebSecurityExpressionHandlerRoleHierarchyBeanConfig.class).autowire(); + TestingAuthenticationToken authentication = new TestingAuthenticationToken("user", "notused", "ROLE_ADMIN"); + FilterInvocation invocation = new FilterInvocation(new MockHttpServletRequest("GET", ""), + new MockHttpServletResponse(), new MockFilterChain()); + + AbstractSecurityExpressionHandler handler = this.spring.getContext().getBean(AbstractSecurityExpressionHandler.class); + EvaluationContext evaluationContext = handler.createEvaluationContext(authentication, invocation); + Expression expression = handler.getExpressionParser() + .parseExpression("hasRole('ROLE_USER')"); + boolean granted = expression.getValue(evaluationContext, Boolean.class); + assertThat(granted).isTrue(); + } + + @EnableWebSecurity + static class WebSecurityExpressionHandlerRoleHierarchyBeanConfig extends WebSecurityConfigurerAdapter { + @Bean + RoleHierarchy roleHierarchy() { + RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl(); + roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER"); + return roleHierarchy; + } + } + @Test public void securityExpressionHandlerWhenPermissionEvaluatorBeanThenPermissionEvaluatorUsed() { this.spring.register(WebSecurityExpressionHandlerPermissionEvaluatorBeanConfig.class).autowire();