mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-01 09:42:13 +00:00
AuthorizeHttpRequestsConfigurer.AuthorizedUrl.hasRole should look up for a RoleHierarchy bean in the context
Closes gh-12473
This commit is contained in:
parent
ce11015e53
commit
d84b8d2d12
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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;
|
package org.springframework.security.config.annotation.web.configurers;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import io.micrometer.observation.ObservationRegistry;
|
import io.micrometer.observation.ObservationRegistry;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import org.springframework.context.ApplicationContext;
|
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.AuthenticatedAuthorizationManager;
|
||||||
import org.springframework.security.authorization.AuthorityAuthorizationManager;
|
import org.springframework.security.authorization.AuthorityAuthorizationManager;
|
||||||
import org.springframework.security.authorization.AuthorizationDecision;
|
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.RequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcherEntry;
|
import org.springframework.security.web.util.matcher.RequestMatcherEntry;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.function.SingletonSupplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a URL based authorization using {@link AuthorizationManager}.
|
* Adds a URL based authorization using {@link AuthorizationManager}.
|
||||||
@ -56,6 +60,8 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
|||||||
|
|
||||||
private final AuthorizationEventPublisher publisher;
|
private final AuthorizationEventPublisher publisher;
|
||||||
|
|
||||||
|
private final Supplier<RoleHierarchy> roleHierarchy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an instance.
|
* Creates an instance.
|
||||||
* @param context the {@link ApplicationContext} to use
|
* @param context the {@link ApplicationContext} to use
|
||||||
@ -68,6 +74,8 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
|||||||
else {
|
else {
|
||||||
this.publisher = new SpringAuthorizationEventPublisher(context);
|
this.publisher = new SpringAuthorizationEventPublisher(context);
|
||||||
}
|
}
|
||||||
|
this.roleHierarchy = SingletonSupplier.of(() -> (context.getBeanNamesForType(RoleHierarchy.class).length > 0)
|
||||||
|
? context.getBean(RoleHierarchy.class) : new NullRoleHierarchy());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -251,7 +259,7 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
|||||||
* customizations
|
* customizations
|
||||||
*/
|
*/
|
||||||
public AuthorizationManagerRequestMatcherRegistry hasRole(String role) {
|
public AuthorizationManagerRequestMatcherRegistry hasRole(String role) {
|
||||||
return access(AuthorityAuthorizationManager.hasRole(role));
|
return access(withRoleHierarchy(AuthorityAuthorizationManager.hasRole(role)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -263,7 +271,7 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
|||||||
* customizations
|
* customizations
|
||||||
*/
|
*/
|
||||||
public AuthorizationManagerRequestMatcherRegistry hasAnyRole(String... roles) {
|
public AuthorizationManagerRequestMatcherRegistry hasAnyRole(String... roles) {
|
||||||
return access(AuthorityAuthorizationManager.hasAnyRole(roles));
|
return access(withRoleHierarchy(AuthorityAuthorizationManager.hasAnyRole(roles)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -273,7 +281,7 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
|||||||
* customizations
|
* customizations
|
||||||
*/
|
*/
|
||||||
public AuthorizationManagerRequestMatcherRegistry hasAuthority(String authority) {
|
public AuthorizationManagerRequestMatcherRegistry hasAuthority(String authority) {
|
||||||
return access(AuthorityAuthorizationManager.hasAuthority(authority));
|
return access(withRoleHierarchy(AuthorityAuthorizationManager.hasAuthority(authority)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -284,7 +292,13 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
|||||||
* customizations
|
* customizations
|
||||||
*/
|
*/
|
||||||
public AuthorizationManagerRequestMatcherRegistry hasAnyAuthority(String... authorities) {
|
public AuthorizationManagerRequestMatcherRegistry hasAnyAuthority(String... authorities) {
|
||||||
return access(AuthorityAuthorizationManager.hasAnyAuthority(authorities));
|
return access(withRoleHierarchy(AuthorityAuthorizationManager.hasAnyAuthority(authorities)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private AuthorityAuthorizationManager<RequestAuthorizationContext> withRoleHierarchy(
|
||||||
|
AuthorityAuthorizationManager<RequestAuthorizationContext> manager) {
|
||||||
|
manager.setRoleHierarchy(AuthorizeHttpRequestsConfigurer.this.roleHierarchy.get());
|
||||||
|
return manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
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.RememberMeAuthenticationToken;
|
||||||
import org.springframework.security.authentication.TestAuthentication;
|
import org.springframework.security.authentication.TestAuthentication;
|
||||||
import org.springframework.security.authorization.AuthorizationDecision;
|
import org.springframework.security.authorization.AuthorizationDecision;
|
||||||
@ -272,6 +274,17 @@ public class AuthorizeHttpRequestsConfigurerTests {
|
|||||||
this.mvc.perform(requestWithAdmin).andExpect(status().isForbidden());
|
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
|
@Test
|
||||||
public void getWhenRoleUserOrAdminConfiguredAndRoleIsUserThenRespondsWithOk() throws Exception {
|
public void getWhenRoleUserOrAdminConfiguredAndRoleIsUserThenRespondsWithOk() throws Exception {
|
||||||
this.spring.register(RoleUserOrAdminConfig.class, BasicController.class).autowire();
|
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
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
static class RoleUserOrAdminConfig {
|
static class RoleUserOrAdminConfig {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user