Polish RoleHierarchy Bean Usage

Issue gh-12783
This commit is contained in:
DerChris173 2023-12-07 18:34:58 +01:00 committed by Josh Cummings
parent b76f7c029d
commit e6bea1cfa1
6 changed files with 44 additions and 35 deletions

View File

@ -22,7 +22,6 @@ import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
@ -53,11 +52,10 @@ final class Jsr250MethodSecurityConfiguration {
static MethodInterceptor jsr250AuthorizationMethodInterceptor(
ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
ObjectProvider<ObservationRegistry> registryProvider, ApplicationContext context) {
ObjectProvider<ObservationRegistry> registryProvider, ObjectProvider<RoleHierarchy> roleHierarchyProvider) {
Jsr250AuthorizationManager jsr250 = new Jsr250AuthorizationManager();
AuthoritiesAuthorizationManager authoritiesAuthorizationManager = new AuthoritiesAuthorizationManager();
RoleHierarchy roleHierarchy = (context.getBeanNamesForType(RoleHierarchy.class).length > 0)
? context.getBean(RoleHierarchy.class) : new NullRoleHierarchy();
RoleHierarchy roleHierarchy = roleHierarchyProvider.getIfAvailable(NullRoleHierarchy::new);
authoritiesAuthorizationManager.setRoleHierarchy(roleHierarchy);
jsr250.setAuthoritiesAuthorizationManager(authoritiesAuthorizationManager);
defaultsProvider.ifAvailable((d) -> jsr250.setRolePrefix(d.getRolePrefix()));

View File

@ -65,11 +65,12 @@ final class PrePostMethodSecurityConfiguration {
static MethodInterceptor preFilterAuthorizationMethodInterceptor(
ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
ObjectProvider<SecurityContextHolderStrategy> strategyProvider, ApplicationContext context) {
ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
ObjectProvider<RoleHierarchy> roleHierarchyProvider, ApplicationContext context) {
PreFilterAuthorizationMethodInterceptor preFilter = new PreFilterAuthorizationMethodInterceptor();
strategyProvider.ifAvailable(preFilter::setSecurityContextHolderStrategy);
preFilter.setExpressionHandler(
new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider, defaultsProvider, context));
preFilter.setExpressionHandler(new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider,
defaultsProvider, roleHierarchyProvider, context));
return preFilter;
}
@ -80,10 +81,11 @@ final class PrePostMethodSecurityConfiguration {
ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
ObjectProvider<AuthorizationEventPublisher> eventPublisherProvider,
ObjectProvider<ObservationRegistry> registryProvider, ApplicationContext context) {
ObjectProvider<ObservationRegistry> registryProvider, ObjectProvider<RoleHierarchy> roleHierarchyProvider,
ApplicationContext context) {
PreAuthorizeAuthorizationManager manager = new PreAuthorizeAuthorizationManager();
manager.setExpressionHandler(
new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider, defaultsProvider, context));
manager.setExpressionHandler(new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider,
defaultsProvider, roleHierarchyProvider, context));
AuthorizationManagerBeforeMethodInterceptor preAuthorize = AuthorizationManagerBeforeMethodInterceptor
.preAuthorize(manager(manager, registryProvider));
strategyProvider.ifAvailable(preAuthorize::setSecurityContextHolderStrategy);
@ -98,10 +100,11 @@ final class PrePostMethodSecurityConfiguration {
ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
ObjectProvider<AuthorizationEventPublisher> eventPublisherProvider,
ObjectProvider<ObservationRegistry> registryProvider, ApplicationContext context) {
ObjectProvider<ObservationRegistry> registryProvider, ObjectProvider<RoleHierarchy> roleHierarchyProvider,
ApplicationContext context) {
PostAuthorizeAuthorizationManager manager = new PostAuthorizeAuthorizationManager();
manager.setExpressionHandler(
new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider, defaultsProvider, context));
manager.setExpressionHandler(new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider,
defaultsProvider, roleHierarchyProvider, context));
AuthorizationManagerAfterMethodInterceptor postAuthorize = AuthorizationManagerAfterMethodInterceptor
.postAuthorize(manager(manager, registryProvider));
strategyProvider.ifAvailable(postAuthorize::setSecurityContextHolderStrategy);
@ -114,19 +117,20 @@ final class PrePostMethodSecurityConfiguration {
static MethodInterceptor postFilterAuthorizationMethodInterceptor(
ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
ObjectProvider<SecurityContextHolderStrategy> strategyProvider, ApplicationContext context) {
ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
ObjectProvider<RoleHierarchy> roleHierarchyProvider, ApplicationContext context) {
PostFilterAuthorizationMethodInterceptor postFilter = new PostFilterAuthorizationMethodInterceptor();
strategyProvider.ifAvailable(postFilter::setSecurityContextHolderStrategy);
postFilter.setExpressionHandler(
new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider, defaultsProvider, context));
postFilter.setExpressionHandler(new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider,
defaultsProvider, roleHierarchyProvider, context));
return postFilter;
}
private static MethodSecurityExpressionHandler defaultExpressionHandler(
ObjectProvider<GrantedAuthorityDefaults> defaultsProvider, ApplicationContext context) {
ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
ObjectProvider<RoleHierarchy> roleHierarchyProvider, ApplicationContext context) {
DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler();
RoleHierarchy roleHierarchy = (context.getBeanNamesForType(RoleHierarchy.class).length > 0)
? context.getBean(RoleHierarchy.class) : new NullRoleHierarchy();
RoleHierarchy roleHierarchy = roleHierarchyProvider.getIfAvailable(NullRoleHierarchy::new);
handler.setRoleHierarchy(roleHierarchy);
defaultsProvider.ifAvailable((d) -> handler.setDefaultRolePrefix(d.getRolePrefix()));
handler.setApplicationContext(context);
@ -144,9 +148,10 @@ final class PrePostMethodSecurityConfiguration {
private DeferringMethodSecurityExpressionHandler(
ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
ObjectProvider<GrantedAuthorityDefaults> defaultsProvider, ApplicationContext applicationContext) {
this.expressionHandler = SingletonSupplier.of(() -> expressionHandlerProvider
.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, applicationContext)));
ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
ObjectProvider<RoleHierarchy> roleHierarchyProvider, ApplicationContext applicationContext) {
this.expressionHandler = SingletonSupplier.of(() -> expressionHandlerProvider.getIfAvailable(
() -> defaultExpressionHandler(defaultsProvider, roleHierarchyProvider, applicationContext)));
}
@Override

View File

@ -22,7 +22,6 @@ import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
@ -52,11 +51,10 @@ final class SecuredMethodSecurityConfiguration {
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
static MethodInterceptor securedAuthorizationMethodInterceptor(
ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
ObjectProvider<ObservationRegistry> registryProvider, ApplicationContext context) {
ObjectProvider<ObservationRegistry> registryProvider, ObjectProvider<RoleHierarchy> roleHierarchyProvider) {
SecuredAuthorizationManager secured = new SecuredAuthorizationManager();
AuthoritiesAuthorizationManager authoritiesAuthorizationManager = new AuthoritiesAuthorizationManager();
RoleHierarchy roleHierarchy = (context.getBeanNamesForType(RoleHierarchy.class).length > 0)
? context.getBean(RoleHierarchy.class) : new NullRoleHierarchy();
RoleHierarchy roleHierarchy = roleHierarchyProvider.getIfAvailable(NullRoleHierarchy::new);
authoritiesAuthorizationManager.setRoleHierarchy(roleHierarchy);
secured.setAuthoritiesAuthorizationManager(authoritiesAuthorizationManager);
SecurityContextHolderStrategy strategy = strategyProvider

View File

@ -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.
@ -50,9 +50,12 @@ public interface MethodSecurityService {
@PermitAll
String jsr250PermitAll();
@RolesAllowed({ "ADMIN", "USER" })
@RolesAllowed("ADMIN")
String jsr250RolesAllowed();
@RolesAllowed("USER")
String jsr250RolesAllowedUser();
@Secured({ "ROLE_USER", "RUN_AS_SUPER" })
Authentication runAs();

View File

@ -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.
@ -56,6 +56,11 @@ public class MethodSecurityServiceImpl implements MethodSecurityService {
return null;
}
@Override
public String jsr250RolesAllowedUser() {
return null;
}
@Override
public Authentication runAs() {
return SecurityContextHolder.getContext().getAuthentication();

View File

@ -453,9 +453,9 @@ public class PrePostMethodSecurityConfigurationTests {
@Test
public void methodSecurityAdminWhenRoleHierarchyBeanAvailableThenUses() {
this.spring.register(RoleHierarchyConfig.class, MethodSecurityServiceConfig.class).autowire();
this.methodSecurityService.preAuthorizeAdmin();
this.methodSecurityService.secured();
this.methodSecurityService.jsr250RolesAllowed();
this.methodSecurityService.preAuthorizeUser();
this.methodSecurityService.securedUser();
this.methodSecurityService.jsr250RolesAllowedUser();
}
@WithMockUser
@ -464,7 +464,7 @@ public class PrePostMethodSecurityConfigurationTests {
this.spring.register(RoleHierarchyConfig.class, MethodSecurityServiceConfig.class).autowire();
this.methodSecurityService.preAuthorizeUser();
this.methodSecurityService.securedUser();
this.methodSecurityService.jsr250RolesAllowed();
this.methodSecurityService.jsr250RolesAllowedUser();
}
private static Consumer<ConfigurableWebApplicationContext> disallowBeanOverriding() {
@ -652,9 +652,9 @@ public class PrePostMethodSecurityConfigurationTests {
static class RoleHierarchyConfig {
@Bean
RoleHierarchy roleHierarchy() {
static RoleHierarchy roleHierarchy() {
RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl();
roleHierarchyImpl.setHierarchy("ADMIN > USER");
roleHierarchyImpl.setHierarchy("ROLE_ADMIN > ROLE_USER");
return roleHierarchyImpl;
}