From d84b8d2d12d6608ba9fb64296fedfa8c3bea24c0 Mon Sep 17 00:00:00 2001 From: Evgeniy Cheban Date: Sun, 8 Jan 2023 19:09:32 +0100 Subject: [PATCH] AuthorizeHttpRequestsConfigurer.AuthorizedUrl.hasRole should look up for a RoleHierarchy bean in the context Closes gh-12473 --- .../AuthorizeHttpRequestsConfigurer.java | 24 +++++++++--- .../AuthorizeHttpRequestsConfigurerTests.java | 39 ++++++++++++++++++- 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurer.java index 0e9d6f96c7..a416c1b1b3 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 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. @@ -17,11 +17,14 @@ package org.springframework.security.config.annotation.web.configurers; import java.util.List; +import java.util.function.Supplier; import io.micrometer.observation.ObservationRegistry; import jakarta.servlet.http.HttpServletRequest; import org.springframework.context.ApplicationContext; +import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy; +import org.springframework.security.access.hierarchicalroles.RoleHierarchy; import org.springframework.security.authorization.AuthenticatedAuthorizationManager; import org.springframework.security.authorization.AuthorityAuthorizationManager; import org.springframework.security.authorization.AuthorizationDecision; @@ -38,6 +41,7 @@ import org.springframework.security.web.access.intercept.RequestMatcherDelegatin import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcherEntry; import org.springframework.util.Assert; +import org.springframework.util.function.SingletonSupplier; /** * Adds a URL based authorization using {@link AuthorizationManager}. @@ -56,6 +60,8 @@ public final class AuthorizeHttpRequestsConfigurer roleHierarchy; + /** * Creates an instance. * @param context the {@link ApplicationContext} to use @@ -68,6 +74,8 @@ public final class AuthorizeHttpRequestsConfigurer (context.getBeanNamesForType(RoleHierarchy.class).length > 0) + ? context.getBean(RoleHierarchy.class) : new NullRoleHierarchy()); } /** @@ -251,7 +259,7 @@ public final class AuthorizeHttpRequestsConfigurer withRoleHierarchy( + AuthorityAuthorizationManager manager) { + manager.setRoleHierarchy(AuthorizeHttpRequestsConfigurer.this.roleHierarchy.get()); + return manager; } /** diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurerTests.java index 40d59f146f..f90c0483a1 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 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. @@ -26,6 +26,8 @@ import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.security.access.hierarchicalroles.RoleHierarchy; +import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl; import org.springframework.security.authentication.RememberMeAuthenticationToken; import org.springframework.security.authentication.TestAuthentication; import org.springframework.security.authorization.AuthorizationDecision; @@ -272,6 +274,17 @@ public class AuthorizeHttpRequestsConfigurerTests { this.mvc.perform(requestWithAdmin).andExpect(status().isForbidden()); } + @Test + public void getWhenHasRoleUserAndRoleHierarchyConfiguredThenGreaterRoleTakesPrecedence() throws Exception { + this.spring.register(RoleHierarchyUserConfig.class, BasicController.class).autowire(); + // @formatter:off + MockHttpServletRequestBuilder requestWithAdmin = get("/") + .with(user("user") + .roles("ADMIN")); + // @formatter:on + this.mvc.perform(requestWithAdmin).andExpect(status().isOk()); + } + @Test public void getWhenRoleUserOrAdminConfiguredAndRoleIsUserThenRespondsWithOk() throws Exception { this.spring.register(RoleUserOrAdminConfig.class, BasicController.class).autowire(); @@ -770,6 +783,30 @@ public class AuthorizeHttpRequestsConfigurerTests { } + @Configuration + @EnableWebSecurity + static class RoleHierarchyUserConfig { + + @Bean + SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + // @formatter:off + return http + .authorizeHttpRequests((requests) -> requests + .anyRequest().hasRole("USER") + ) + .build(); + // @formatter:on + } + + @Bean + RoleHierarchy roleHierarchy() { + RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl(); + roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER"); + return roleHierarchy; + } + + } + @Configuration @EnableWebSecurity static class RoleUserOrAdminConfig {