diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/Jsr250MethodSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/Jsr250MethodSecurityConfiguration.java index f3f0f18364..938d53661a 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/Jsr250MethodSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/Jsr250MethodSecurityConfiguration.java @@ -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 defaultsProvider, ObjectProvider strategyProvider, - ObjectProvider registryProvider, ApplicationContext context) { + ObjectProvider registryProvider, ObjectProvider 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())); diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfiguration.java index 208b0921dc..51c497eba3 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfiguration.java @@ -65,11 +65,12 @@ final class PrePostMethodSecurityConfiguration { static MethodInterceptor preFilterAuthorizationMethodInterceptor( ObjectProvider defaultsProvider, ObjectProvider expressionHandlerProvider, - ObjectProvider strategyProvider, ApplicationContext context) { + ObjectProvider strategyProvider, + ObjectProvider 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 expressionHandlerProvider, ObjectProvider strategyProvider, ObjectProvider eventPublisherProvider, - ObjectProvider registryProvider, ApplicationContext context) { + ObjectProvider registryProvider, ObjectProvider 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 expressionHandlerProvider, ObjectProvider strategyProvider, ObjectProvider eventPublisherProvider, - ObjectProvider registryProvider, ApplicationContext context) { + ObjectProvider registryProvider, ObjectProvider 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 defaultsProvider, ObjectProvider expressionHandlerProvider, - ObjectProvider strategyProvider, ApplicationContext context) { + ObjectProvider strategyProvider, + ObjectProvider 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 defaultsProvider, ApplicationContext context) { + ObjectProvider defaultsProvider, + ObjectProvider 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 expressionHandlerProvider, - ObjectProvider defaultsProvider, ApplicationContext applicationContext) { - this.expressionHandler = SingletonSupplier.of(() -> expressionHandlerProvider - .getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, applicationContext))); + ObjectProvider defaultsProvider, + ObjectProvider roleHierarchyProvider, ApplicationContext applicationContext) { + this.expressionHandler = SingletonSupplier.of(() -> expressionHandlerProvider.getIfAvailable( + () -> defaultExpressionHandler(defaultsProvider, roleHierarchyProvider, applicationContext))); } @Override diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/SecuredMethodSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/SecuredMethodSecurityConfiguration.java index e42efb66a6..4e10150dc1 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/SecuredMethodSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/SecuredMethodSecurityConfiguration.java @@ -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 strategyProvider, - ObjectProvider registryProvider, ApplicationContext context) { + ObjectProvider registryProvider, ObjectProvider 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 diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityService.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityService.java index 9dddcad251..f7db88a33c 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityService.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityService.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. @@ -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(); diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityServiceImpl.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityServiceImpl.java index b414b2d93a..133395e911 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityServiceImpl.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityServiceImpl.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. @@ -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(); diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfigurationTests.java index 9458d363df..d9138d4a33 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfigurationTests.java @@ -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 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; }