From 3a1692f3c35317ef75a9404a6a6f6e75ee6fbe45 Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Tue, 2 Sep 2025 18:45:09 -0600 Subject: [PATCH 1/6] Remove Direct Runtime Dependency on Access API Issue gh-17847 --- .../web/builders/FilterOrderRegistration.java | 7 +- .../annotation/web/builders/WebSecurity.java | 115 ++++++++++++++---- .../WebSecurityFilterChainValidator.java | 14 ++- .../http/DefaultFilterChainValidator.java | 97 ++++++++++----- .../WebSecurityConfigurationTests.java | 3 +- .../showcase/WithMockUserParentTests.java | 6 +- .../context/showcase/WithMockUserTests.java | 10 +- .../showcase/WithUserDetailsTests.java | 10 +- 8 files changed, 196 insertions(+), 66 deletions(-) diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/builders/FilterOrderRegistration.java b/config/src/main/java/org/springframework/security/config/annotation/web/builders/FilterOrderRegistration.java index 89e2fe007e..063ced5e88 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/builders/FilterOrderRegistration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/builders/FilterOrderRegistration.java @@ -23,9 +23,7 @@ import java.util.Map; import jakarta.servlet.Filter; import org.springframework.security.web.access.ExceptionTranslationFilter; -import org.springframework.security.web.access.channel.ChannelProcessingFilter; import org.springframework.security.web.access.intercept.AuthorizationFilter; -import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; import org.springframework.security.web.authentication.AnonymousAuthenticationFilter; import org.springframework.security.web.authentication.AuthenticationFilter; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; @@ -78,7 +76,7 @@ final class FilterOrderRegistration { Step order = new Step(INITIAL_ORDER, ORDER_STEP); put(DisableEncodeUrlFilter.class, order.next()); put(ForceEagerSessionCreationFilter.class, order.next()); - put(ChannelProcessingFilter.class, order.next()); + this.filterToOrder.put("org.springframework.security.web.access.channel.ChannelProcessingFilter", order.next()); put(HttpsRedirectFilter.class, order.next()); order.next(); // gh-8105 put(WebAsyncManagerIntegrationFilter.class, order.next()); @@ -126,7 +124,8 @@ final class FilterOrderRegistration { order.next()); put(SessionManagementFilter.class, order.next()); put(ExceptionTranslationFilter.class, order.next()); - put(FilterSecurityInterceptor.class, order.next()); + this.filterToOrder.put("org.springframework.security.web.access.intercept.FilterSecurityInterceptor", + order.next()); put(AuthorizationFilter.class, order.next()); put(SwitchUserFilter.class, order.next()); } 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 943cfbc802..bce1b3bdf2 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 @@ -18,6 +18,7 @@ package org.springframework.security.config.annotation.web.builders; import java.util.ArrayList; import java.util.List; +import java.util.function.Supplier; import io.micrometer.observation.ObservationRegistry; import jakarta.servlet.Filter; @@ -25,6 +26,8 @@ import jakarta.servlet.ServletContext; import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; import org.springframework.beans.BeansException; import org.springframework.beans.factory.NoSuchBeanDefinitionException; @@ -32,8 +35,11 @@ import org.springframework.beans.factory.ObjectProvider; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.core.ResolvableType; +import org.springframework.expression.EvaluationContext; 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.expression.SecurityExpressionOperations; import org.springframework.security.access.hierarchicalroles.RoleHierarchy; import org.springframework.security.authorization.AuthorizationDecision; import org.springframework.security.authorization.AuthorizationManager; @@ -46,6 +52,7 @@ import org.springframework.security.config.annotation.web.WebSecurityConfigurer; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration; import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; +import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.web.DefaultSecurityFilterChain; import org.springframework.security.web.FilterChainProxy; @@ -58,7 +65,7 @@ import org.springframework.security.web.access.DefaultWebInvocationPrivilegeEval import org.springframework.security.web.access.PathPatternRequestTransformer; import org.springframework.security.web.access.RequestMatcherDelegatingWebInvocationPrivilegeEvaluator; import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator; -import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler; +import org.springframework.security.web.access.expression.DefaultHttpSecurityExpressionHandler; import org.springframework.security.web.access.intercept.AuthorizationFilter; import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; import org.springframework.security.web.access.intercept.RequestAuthorizationContext; @@ -74,6 +81,7 @@ import org.springframework.security.web.util.matcher.AnyRequestMatcher; 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.ClassUtils; import org.springframework.web.context.ServletContextAware; import org.springframework.web.filter.DelegatingFilterProxy; @@ -99,6 +107,9 @@ import org.springframework.web.filter.DelegatingFilterProxy; public final class WebSecurity extends AbstractConfiguredSecurityBuilder implements SecurityBuilder, ApplicationContextAware, ServletContextAware { + private static final boolean USING_ACCESS = ClassUtils + .isPresent("org.springframework.security.access.SecurityConfig", null); + private final Log logger = LogFactory.getLog(getClass()); private final List ignoredRequests = new ArrayList<>(); @@ -122,9 +133,10 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder expressionHandler = this.defaultWebSecurityExpressionHandler; + private SecurityExpressionHandler expressionHandler = new SecurityExpressionHandlerAdapter( + this.defaultExpressionHandler); private Runnable postBuildAction = () -> { }; @@ -240,7 +252,7 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder authorizationManager = (authentication, context) -> { - HttpServletRequest request = context.getRequest(); - boolean result = privilegeEvaluator.isAllowed(request.getContextPath(), request.getRequestURI(), - request.getMethod(), authentication.get()); - return new AuthorizationDecision(result); - }; - builder.add(securityFilterChain::matches, authorizationManager); - mappings = true; - continue; + if (USING_ACCESS) { + mappings = AccessComponents.addAuthorizationManager(filter, this.servletContext, builder, + securityFilterChain); } if (filter instanceof AuthorizationFilter authorization) { AuthorizationManager authorizationManager = authorization.getAuthorizationManager(); @@ -388,15 +390,14 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder { + + private final AbstractSecurityExpressionHandler delegate; + + private SecurityExpressionHandlerAdapter( + AbstractSecurityExpressionHandler delegate) { + this.delegate = delegate; + } + + @Override + public EvaluationContext createEvaluationContext(Supplier authentication, + FilterInvocation invocation) { + RequestAuthorizationContext context = new RequestAuthorizationContext(invocation.getRequest()); + return this.delegate.createEvaluationContext(authentication, context); + } + + @Override + protected SecurityExpressionOperations createSecurityExpressionRoot(@Nullable Authentication authentication, + FilterInvocation invocation) { + RequestAuthorizationContext context = new RequestAuthorizationContext(invocation.getRequest()); + Object operations = this.delegate.createEvaluationContext(authentication, context) + .getRootObject() + .getValue(); + Assert.isInstanceOf(SecurityExpressionOperations.class, operations, + "createEvaluationContext must have a SecurityExpressionOperations instance as its root"); + return (SecurityExpressionOperations) operations; + } + + @Override + public void setApplicationContext(ApplicationContext context) { + this.delegate.setApplicationContext(context); + super.setApplicationContext(context); + } + + @Override + public void setPermissionEvaluator(PermissionEvaluator permissionEvaluator) { + this.delegate.setPermissionEvaluator(permissionEvaluator); + super.setPermissionEvaluator(permissionEvaluator); + } + + @Override + public void setRoleHierarchy(@Nullable RoleHierarchy roleHierarchy) { + this.delegate.setRoleHierarchy(roleHierarchy); + super.setRoleHierarchy(roleHierarchy); + } + + } + + private static final class AccessComponents { + + private static boolean addAuthorizationManager(Filter filter, ServletContext servletContext, + RequestMatcherDelegatingAuthorizationManager.Builder builder, SecurityFilterChain securityFilterChain) { + if (filter instanceof FilterSecurityInterceptor securityInterceptor) { + DefaultWebInvocationPrivilegeEvaluator privilegeEvaluator = new DefaultWebInvocationPrivilegeEvaluator( + securityInterceptor); + privilegeEvaluator.setServletContext(servletContext); + AuthorizationManager authorizationManager = (authentication, context) -> { + HttpServletRequest request = context.getRequest(); + boolean result = privilegeEvaluator.isAllowed(request.getContextPath(), request.getRequestURI(), + request.getMethod(), authentication.get()); + return new AuthorizationDecision(result); + }; + builder.add(securityFilterChain::matches, authorizationManager); + return true; + } + return false; + } + + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurityFilterChainValidator.java b/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurityFilterChainValidator.java index 971b2cf810..fa97043fb6 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurityFilterChainValidator.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurityFilterChainValidator.java @@ -29,6 +29,7 @@ import org.springframework.security.web.UnreachableFilterChainException; import org.springframework.security.web.access.intercept.AuthorizationFilter; import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; import org.springframework.security.web.util.matcher.AnyRequestMatcher; +import org.springframework.util.ClassUtils; /** * A filter chain validator for filter chains built by {@link WebSecurity} @@ -39,6 +40,9 @@ import org.springframework.security.web.util.matcher.AnyRequestMatcher; */ final class WebSecurityFilterChainValidator implements FilterChainProxy.FilterChainValidator { + private static final boolean USING_ACCESS = ClassUtils + .isPresent("org.springframework.security.access.SecurityConfig", null); + private final Log logger = LogFactory.getLog(getClass()); @Override @@ -93,7 +97,7 @@ final class WebSecurityFilterChainValidator implements FilterChainProxy.FilterCh if (filter instanceof AuthorizationFilter) { authorizationFilter = filter; } - if (filter instanceof FilterSecurityInterceptor) { + if (USING_ACCESS && AccessComponents.isFilterSecurityInterceptor(filter)) { filterSecurityInterceptor = filter; } } @@ -110,4 +114,12 @@ final class WebSecurityFilterChainValidator implements FilterChainProxy.FilterCh } } + private static final class AccessComponents { + + private static boolean isFilterSecurityInterceptor(Filter filter) { + return filter instanceof FilterSecurityInterceptor; + } + + } + } diff --git a/config/src/main/java/org/springframework/security/config/http/DefaultFilterChainValidator.java b/config/src/main/java/org/springframework/security/config/http/DefaultFilterChainValidator.java index a7dcbbdd98..fb88f14b3a 100644 --- a/config/src/main/java/org/springframework/security/config/http/DefaultFilterChainValidator.java +++ b/config/src/main/java/org/springframework/security/config/http/DefaultFilterChainValidator.java @@ -56,9 +56,13 @@ import org.springframework.security.web.jaasapi.JaasApiIntegrationFilter; import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter; import org.springframework.security.web.session.SessionManagementFilter; import org.springframework.security.web.util.matcher.AnyRequestMatcher; +import org.springframework.util.ClassUtils; public class DefaultFilterChainValidator implements FilterChainProxy.FilterChainValidator { + private static final boolean USING_ACCESS = ClassUtils + .isPresent("org.springframework.security.access.SecurityConfig", null); + private static final Authentication TEST = new TestingAuthenticationToken("", "", Collections.emptyList()); private final Log logger = LogFactory.getLog(getClass()); @@ -120,7 +124,7 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain if (filter instanceof AuthorizationFilter) { authorizationFilter = filter; } - if (filter instanceof FilterSecurityInterceptor) { + if (USING_ACCESS && AccessComponents.isFilterSecurityInterceptor(filter)) { filterSecurityInterceptor = filter; } } @@ -138,7 +142,7 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain } @SuppressWarnings({ "unchecked" }) - private F getFilter(Class type, List filters) { + private static F getFilter(Class type, List filters) { for (Filter f : filters) { if (type.isAssignableFrom(f.getClass())) { return (F) f; @@ -158,7 +162,9 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain checkForDuplicates(SecurityContextHolderAwareRequestFilter.class, filters); checkForDuplicates(JaasApiIntegrationFilter.class, filters); checkForDuplicates(ExceptionTranslationFilter.class, filters); - checkForDuplicates(FilterSecurityInterceptor.class, filters); + if (USING_ACCESS) { + checkForDuplicates(AccessComponents.getFilterSecurityInterceptorClass(), filters); + } checkForDuplicates(AuthorizationFilter.class, filters); } @@ -243,19 +249,11 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain } private boolean checkLoginPageIsPublic(List filters, HttpServletRequest loginRequest) { - FilterSecurityInterceptor authorizationInterceptor = getFilter(FilterSecurityInterceptor.class, filters); - if (authorizationInterceptor != null) { - FilterInvocationSecurityMetadataSource fids = authorizationInterceptor.getSecurityMetadataSource(); - Collection attributes = fids.getAttributes(loginRequest); - if (attributes == null) { - this.logger.debug("No access attributes defined for login page URL"); - if (authorizationInterceptor.isRejectPublicInvocations()) { - this.logger.warn("FilterSecurityInterceptor is configured to reject public invocations." - + " Your login page may not be accessible."); - } - return true; + if (USING_ACCESS) { + Boolean isPublic = AccessComponents.checkLoginPageIsPublic(filters, loginRequest); + if (isPublic != null) { + return isPublic; } - return false; } AuthorizationFilter authorizationFilter = getFilter(AuthorizationFilter.class, filters); if (authorizationFilter != null) { @@ -274,19 +272,11 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain private Supplier deriveAnonymousCheck(List filters, HttpServletRequest loginRequest, AnonymousAuthenticationToken token) { - FilterSecurityInterceptor authorizationInterceptor = getFilter(FilterSecurityInterceptor.class, filters); - if (authorizationInterceptor != null) { - return () -> { - FilterInvocationSecurityMetadataSource source = authorizationInterceptor.getSecurityMetadataSource(); - Collection attributes = source.getAttributes(loginRequest); - try { - authorizationInterceptor.getAccessDecisionManager().decide(token, loginRequest, attributes); - return true; - } - catch (AccessDeniedException ex) { - return false; - } - }; + if (USING_ACCESS) { + Supplier check = AccessComponents.getAnonymousCheck(filters, loginRequest, token); + if (check != null) { + return check; + } } AuthorizationFilter authorizationFilter = getFilter(AuthorizationFilter.class, filters); if (authorizationFilter != null) { @@ -300,4 +290,55 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain return () -> true; } + private static final class AccessComponents { + + private static final Log logger = LogFactory.getLog(DefaultFilterChainValidator.class); + + private static boolean isFilterSecurityInterceptor(Filter filter) { + return filter instanceof FilterSecurityInterceptor; + } + + private static Class getFilterSecurityInterceptorClass() { + return FilterSecurityInterceptor.class; + } + + private static Boolean checkLoginPageIsPublic(List filters, HttpServletRequest loginRequest) { + FilterSecurityInterceptor authorizationInterceptor = getFilter(FilterSecurityInterceptor.class, filters); + if (authorizationInterceptor == null) { + return null; + } + FilterInvocationSecurityMetadataSource fids = authorizationInterceptor.getSecurityMetadataSource(); + Collection attributes = fids.getAttributes(loginRequest); + if (attributes == null) { + logger.debug("No access attributes defined for login page URL"); + if (authorizationInterceptor.isRejectPublicInvocations()) { + logger.warn("FilterSecurityInterceptor is configured to reject public invocations." + + " Your login page may not be accessible."); + } + return true; + } + return false; + } + + private static Supplier getAnonymousCheck(List filters, HttpServletRequest loginRequest, + AnonymousAuthenticationToken token) { + FilterSecurityInterceptor authorizationInterceptor = getFilter(FilterSecurityInterceptor.class, filters); + if (authorizationInterceptor == null) { + return null; + } + return () -> { + FilterInvocationSecurityMetadataSource source = authorizationInterceptor.getSecurityMetadataSource(); + Collection attributes = source.getAttributes(loginRequest); + try { + authorizationInterceptor.getAccessDecisionManager().decide(token, loginRequest, attributes); + return true; + } + catch (AccessDeniedException ex) { + return false; + } + }; + } + + } + } 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 2063563122..922a336e62 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 @@ -60,7 +60,6 @@ import org.springframework.security.web.access.AuthorizationManagerWebInvocation import org.springframework.security.web.access.PathPatternRequestTransformer; import org.springframework.security.web.access.RequestMatcherDelegatingWebInvocationPrivilegeEvaluator; import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator; -import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler; import org.springframework.security.web.access.expression.WebExpressionAuthorizationManager; import org.springframework.test.web.servlet.MockMvc; import org.springframework.util.ClassUtils; @@ -153,7 +152,7 @@ public class WebSecurityConfigurationTests { public void loadConfigWhenDefaultSecurityExpressionHandlerThenDefaultIsRegistered() { this.spring.register(WebSecurityExpressionHandlerDefaultsConfig.class).autowire(); assertThat(this.spring.getContext().getBean(SecurityExpressionHandler.class)) - .isInstanceOf(DefaultWebSecurityExpressionHandler.class); + .isInstanceOf(AbstractSecurityExpressionHandler.class); } @Test diff --git a/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserParentTests.java b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserParentTests.java index ae6df8c9b9..5887e51381 100644 --- a/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserParentTests.java +++ b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserParentTests.java @@ -23,7 +23,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.test.context.showcase.service.HelloMessageService; import org.springframework.security.test.context.showcase.service.MessageService; import org.springframework.test.context.ContextConfiguration; @@ -48,7 +49,8 @@ public class WithMockUserParentTests extends WithMockUserParent { } @Configuration - @EnableGlobalMethodSecurity(prePostEnabled = true) + @EnableMethodSecurity + @EnableWebSecurity @ComponentScan(basePackageClasses = HelloMessageService.class) static class Config { diff --git a/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserTests.java b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserTests.java index 4fb697a878..bdffd8b3e7 100644 --- a/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserTests.java +++ b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserTests.java @@ -31,7 +31,8 @@ import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.AliasFor; import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.test.context.showcase.service.HelloMessageService; import org.springframework.security.test.context.showcase.service.MessageService; import org.springframework.security.test.context.support.WithMockUser; @@ -53,8 +54,8 @@ public class WithMockUserTests { @Test public void getMessageUnauthenticated() { - assertThatExceptionOfType(AuthenticationCredentialsNotFoundException.class) - .isThrownBy(() -> this.messageService.getMessage()); + assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> this.messageService.getMessage()) + .withRootCauseInstanceOf(AuthenticationCredentialsNotFoundException.class); } @Test @@ -104,7 +105,8 @@ public class WithMockUserTests { assertThat(message).contains("admin").contains("ADMIN").contains("ROLE_ADMIN"); } - @EnableGlobalMethodSecurity(prePostEnabled = true) + @EnableMethodSecurity + @EnableWebSecurity @ComponentScan(basePackageClasses = HelloMessageService.class) static class Config { diff --git a/test/src/test/java/org/springframework/security/test/context/showcase/WithUserDetailsTests.java b/test/src/test/java/org/springframework/security/test/context/showcase/WithUserDetailsTests.java index 77c403c909..5473335e11 100644 --- a/test/src/test/java/org/springframework/security/test/context/showcase/WithUserDetailsTests.java +++ b/test/src/test/java/org/springframework/security/test/context/showcase/WithUserDetailsTests.java @@ -25,7 +25,8 @@ import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; @@ -51,8 +52,8 @@ public class WithUserDetailsTests { @Test public void getMessageUnauthenticated() { - assertThatExceptionOfType(AuthenticationCredentialsNotFoundException.class) - .isThrownBy(() -> this.messageService.getMessage()); + assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> this.messageService.getMessage()) + .withRootCauseInstanceOf(AuthenticationCredentialsNotFoundException.class); } @Test @@ -84,7 +85,8 @@ public class WithUserDetailsTests { } @Configuration - @EnableGlobalMethodSecurity(prePostEnabled = true) + @EnableMethodSecurity + @EnableWebSecurity @ComponentScan(basePackageClasses = HelloMessageService.class) static class Config { From eedcec9d5c3652bab7bde318109a1b5c332a96c1 Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Thu, 28 Aug 2025 11:00:46 -0600 Subject: [PATCH 2/6] Move Core Access API Issue gh-17847 --- access/spring-security-access.gradle | 42 ++++++++++ .../access/AccessDecisionManager.java | 0 .../security/access/AccessDecisionVoter.java | 0 .../access/AfterInvocationProvider.java | 0 .../security/access/ConfigAttribute.java | 0 .../security/access/SecurityConfig.java | 0 .../access/SecurityMetadataSource.java | 0 .../AnnotationMetadataExtractor.java | 0 .../Jsr250MethodSecurityMetadataSource.java | 0 .../annotation/Jsr250SecurityConfig.java | 0 .../access/annotation/Jsr250Voter.java | 0 ...curedAnnotationSecurityMetadataSource.java | 0 .../access/annotation/package-info.java | 23 +++++ .../event/AbstractAuthorizationEvent.java | 0 ...uthenticationCredentialsNotFoundEvent.java | 0 .../event/AuthorizationFailureEvent.java | 0 .../access/event/AuthorizedEvent.java | 0 .../security/access/event/LoggerListener.java | 0 .../access/event/PublicInvocationEvent.java | 0 .../security/access/event/package-info.java | 0 ...tExpressionBasedMethodConfigAttribute.java | 0 ...essionBasedAnnotationAttributeFactory.java | 0 .../ExpressionBasedPostInvocationAdvice.java | 0 .../ExpressionBasedPreInvocationAdvice.java | 0 .../PostInvocationExpressionAttribute.java | 0 .../PreInvocationExpressionAttribute.java | 0 .../expression/method/package-info.java | 25 ++++++ .../AbstractSecurityInterceptor.java | 0 .../intercept/AfterInvocationManager.java | 0 .../AfterInvocationProviderManager.java | 0 .../intercept/InterceptorStatusToken.java | 0 .../MethodInvocationPrivilegeEvaluator.java | 0 .../access/intercept/NullRunAsManager.java | 0 .../RunAsImplAuthenticationProvider.java | 0 .../access/intercept/RunAsManager.java | 0 .../access/intercept/RunAsManagerImpl.java | 0 .../access/intercept/RunAsUserToken.java | 0 .../MethodSecurityInterceptor.java | 0 .../MethodSecurityMetadataSourceAdvisor.java | 0 .../intercept/aopalliance/package-info.java | 0 .../intercept/aspectj/AspectJCallback.java | 0 .../AspectJMethodSecurityInterceptor.java | 0 .../aspectj/MethodInvocationAdapter.java | 0 .../intercept/aspectj/package-info.java | 0 .../access/intercept/package-info.java | 0 ...tFallbackMethodSecurityMetadataSource.java | 0 .../AbstractMethodSecurityMetadataSource.java | 0 ...elegatingMethodSecurityMetadataSource.java | 0 .../MapBasedMethodSecurityMetadataSource.java | 0 .../method/MethodSecurityMetadataSource.java | 0 .../security/access/method/P.java | 0 .../security/access/method/package-info.java | 0 .../security/access/package-info.java | 27 ++++++ .../prepost/PostInvocationAdviceProvider.java | 0 .../prepost/PostInvocationAttribute.java | 0 .../PostInvocationAuthorizationAdvice.java | 0 .../prepost/PreInvocationAttribute.java | 0 .../PreInvocationAuthorizationAdvice.java | 0 ...PreInvocationAuthorizationAdviceVoter.java | 0 ...rePostAdviceReactiveMethodInterceptor.java | 0 ...ePostAnnotationSecurityMetadataSource.java | 0 .../PrePostInvocationAttributeFactory.java | 0 .../security/access/prepost/package-info.java | 27 ++++++ .../vote/AbstractAccessDecisionManager.java | 0 .../access/vote/AbstractAclVoter.java | 0 .../access/vote/AffirmativeBased.java | 0 .../access/vote/AuthenticatedVoter.java | 0 .../security/access/vote/ConsensusBased.java | 0 .../access/vote/RoleHierarchyVoter.java | 0 .../security/access/vote/RoleVoter.java | 0 .../security/access/vote/UnanimousBased.java | 0 .../security/access/vote/package-info.java | 0 ...ticationCredentialsNotFoundEventTests.java | 0 .../AuthorizationFailureEventTests.java | 0 .../security/access/AuthorizedEventTests.java | 0 .../security/access/ITargetObject.java | 36 ++++++++ .../security/access/OtherTargetObject.java | 53 ++++++++++++ .../security/access/SecurityConfigTests.java | 0 .../security/access/TargetObject.java | 81 ++++++++++++++++++ .../access/annotation/BusinessService.java | 0 .../annotation/BusinessServiceImpl.java | 0 .../security/access/annotation/Entity.java | 0 ...xpressionProtectedBusinessServiceImpl.java | 0 .../annotation/Jsr250BusinessServiceImpl.java | 0 ...r250MethodSecurityMetadataSourceTests.java | 0 .../access/annotation/Jsr250VoterTests.java | 0 .../access/annotation/RequireAdminRole.java | 0 .../access/annotation/RequireUserRole.java | 0 ...AnnotationSecurityMetadataSourceTests.java | 3 +- .../annotation/sec2150/CrudRepository.java | 0 .../sec2150/MethodInvocationFactory.java | 0 .../annotation/sec2150/PersonRepository.java | 0 ...tMethodSecurityExpressionHandlerTests.java | 0 ...pressionBasedPreInvocationAdviceTests.java | 0 .../method/MethodExpressionVoterTests.java | 0 .../MethodSecurityEvaluationContextTests.java | 0 .../MethodSecurityExpressionRootTests.java | 24 +++--- ...AnnotationSecurityMetadataSourceTests.java | 0 .../expression/method/SecurityRules.java | 0 .../AbstractSecurityInterceptorTests.java | 0 .../AfterInvocationProviderManagerTests.java | 0 .../InterceptorStatusTokenTests.java | 0 .../intercept/NullRunAsManagerTests.java | 0 .../RunAsImplAuthenticationProviderTests.java | 0 .../intercept/RunAsManagerImplTests.java | 0 .../access/intercept/RunAsUserTokenTests.java | 0 .../MethodSecurityInterceptorTests.java | 4 +- ...hodSecurityMetadataSourceAdvisorTests.java | 2 +- ...AspectJMethodSecurityInterceptorTests.java | 2 +- ...asedMethodSecurityMetadataSourceTests.java | 0 ...thodInvocationPrivilegeEvaluatorTests.java | 6 +- .../method/MockMethodInvocation.java | 0 ...tingMethodSecurityMetadataSourceTests.java | 0 .../PostInvocationAdviceProviderTests.java | 0 ...vocationAuthorizationAdviceVoterTests.java | 0 .../AbstractAccessDecisionManagerTests.java | 0 .../access/vote/AbstractAclVoterTests.java | 0 .../access/vote/AffirmativeBasedTests.java | 0 .../access/vote/AuthenticatedVoterTests.java | 0 .../access/vote/ConsensusBasedTests.java | 0 .../security/access/vote/DenyAgainVoter.java | 0 .../security/access/vote/DenyVoter.java | 0 .../access/vote/RoleHierarchyVoterTests.java | 0 .../security/access/vote/RoleVoterTests.java | 0 .../access/vote/UnanimousBasedTests.java | 0 acl/spring-security-acl.gradle | 2 + aspects/spring-security-aspects.gradle | 2 + config/spring-security-config.gradle | 3 +- .../AnnotationParameterNameDiscoverer.java | 1 - ...erAfterReactiveMethodInterceptorTests.java | 1 - ...rBeforeReactiveMethodInterceptorTests.java | 1 - .../authorization/method/BusinessService.java | 70 ++++++++++++++++ .../Jsr250AuthorizationManagerTests.java | 1 - ...odExpressionAuthorizationManagerTests.java | 1 - .../method/MockMethodInvocation.java | 75 +++++++++++++++++ ...ostAuthorizeAuthorizationManagerTests.java | 1 - ...rizeReactiveAuthorizationManagerTests.java | 1 - ...erAuthorizationMethodInterceptorTests.java | 1 - ...izationReactiveMethodInterceptorTests.java | 1 - ...PreAuthorizeAuthorizationManagerTests.java | 1 - ...rizeReactiveAuthorizationManagerTests.java | 1 - ...erAuthorizationMethodInterceptorTests.java | 1 - ...izationReactiveMethodInterceptorTests.java | 1 - .../method/RequireAdminRole.java | 33 ++++++++ .../authorization/method/RequireUserRole.java | 33 ++++++++ .../SecuredAuthorizationManagerTests.java | 1 - ...nnotationParameterNameDiscovererTests.java | 1 - .../security/util/BusinessService.java | 70 ++++++++++++++++ .../security/util/BusinessServiceImpl.java | 84 +++++++++++++++++++ .../springframework/security/util/Entity.java | 30 +++++++ .../util/MethodInvocationUtilsTests.java | 1 - .../security/util/RequireAdminRole.java | 33 ++++++++ .../security/util/RequireUserRole.java | 33 ++++++++ .../spring-security-itest-context.gradle | 1 + itest/web/spring-security-itest-web.gradle | 1 + messaging/spring-security-messaging.gradle | 1 + web/spring-security-web.gradle | 1 + 157 files changed, 805 insertions(+), 38 deletions(-) create mode 100644 access/spring-security-access.gradle rename {core => access}/src/main/java/org/springframework/security/access/AccessDecisionManager.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/AccessDecisionVoter.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/AfterInvocationProvider.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/ConfigAttribute.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/SecurityConfig.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/SecurityMetadataSource.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/annotation/AnnotationMetadataExtractor.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/annotation/Jsr250MethodSecurityMetadataSource.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/annotation/Jsr250SecurityConfig.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/annotation/Jsr250Voter.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSource.java (100%) create mode 100644 access/src/main/java/org/springframework/security/access/annotation/package-info.java rename {core => access}/src/main/java/org/springframework/security/access/event/AbstractAuthorizationEvent.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/event/AuthenticationCredentialsNotFoundEvent.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/event/AuthorizationFailureEvent.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/event/AuthorizedEvent.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/event/LoggerListener.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/event/PublicInvocationEvent.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/event/package-info.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/expression/method/AbstractExpressionBasedMethodConfigAttribute.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedAnnotationAttributeFactory.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedPostInvocationAdvice.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdvice.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/expression/method/PostInvocationExpressionAttribute.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/expression/method/PreInvocationExpressionAttribute.java (100%) create mode 100644 access/src/main/java/org/springframework/security/access/expression/method/package-info.java rename {core => access}/src/main/java/org/springframework/security/access/intercept/AbstractSecurityInterceptor.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/intercept/AfterInvocationManager.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/intercept/AfterInvocationProviderManager.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/intercept/InterceptorStatusToken.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/intercept/MethodInvocationPrivilegeEvaluator.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/intercept/NullRunAsManager.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/intercept/RunAsImplAuthenticationProvider.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/intercept/RunAsManager.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/intercept/RunAsManagerImpl.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/intercept/RunAsUserToken.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptor.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisor.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/intercept/aopalliance/package-info.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/intercept/aspectj/AspectJCallback.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptor.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/intercept/aspectj/MethodInvocationAdapter.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/intercept/aspectj/package-info.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/intercept/package-info.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/method/AbstractFallbackMethodSecurityMetadataSource.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/method/AbstractMethodSecurityMetadataSource.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSource.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/method/MapBasedMethodSecurityMetadataSource.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/method/MethodSecurityMetadataSource.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/method/P.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/method/package-info.java (100%) create mode 100644 access/src/main/java/org/springframework/security/access/package-info.java rename {core => access}/src/main/java/org/springframework/security/access/prepost/PostInvocationAdviceProvider.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/prepost/PostInvocationAttribute.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/prepost/PostInvocationAuthorizationAdvice.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/prepost/PreInvocationAttribute.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdvice.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoter.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/prepost/PrePostAdviceReactiveMethodInterceptor.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/prepost/PrePostAnnotationSecurityMetadataSource.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/prepost/PrePostInvocationAttributeFactory.java (100%) create mode 100644 access/src/main/java/org/springframework/security/access/prepost/package-info.java rename {core => access}/src/main/java/org/springframework/security/access/vote/AbstractAccessDecisionManager.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/vote/AbstractAclVoter.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/vote/AffirmativeBased.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/vote/AuthenticatedVoter.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/vote/ConsensusBased.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/vote/RoleHierarchyVoter.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/vote/RoleVoter.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/vote/UnanimousBased.java (100%) rename {core => access}/src/main/java/org/springframework/security/access/vote/package-info.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/AuthenticationCredentialsNotFoundEventTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/AuthorizationFailureEventTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/AuthorizedEventTests.java (100%) create mode 100644 access/src/test/java/org/springframework/security/access/ITargetObject.java create mode 100644 access/src/test/java/org/springframework/security/access/OtherTargetObject.java rename {core => access}/src/test/java/org/springframework/security/access/SecurityConfigTests.java (100%) create mode 100644 access/src/test/java/org/springframework/security/access/TargetObject.java rename {core => access}/src/test/java/org/springframework/security/access/annotation/BusinessService.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/annotation/BusinessServiceImpl.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/annotation/Entity.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/annotation/ExpressionProtectedBusinessServiceImpl.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/annotation/Jsr250BusinessServiceImpl.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/annotation/Jsr250MethodSecurityMetadataSourceTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/annotation/Jsr250VoterTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/annotation/RequireAdminRole.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/annotation/RequireUserRole.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSourceTests.java (98%) rename {core => access}/src/test/java/org/springframework/security/access/annotation/sec2150/CrudRepository.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/annotation/sec2150/MethodInvocationFactory.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/annotation/sec2150/PersonRepository.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandlerTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdviceTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/expression/method/MethodExpressionVoterTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/expression/method/MethodSecurityEvaluationContextTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRootTests.java (84%) rename {core => access}/src/test/java/org/springframework/security/access/expression/method/PrePostAnnotationSecurityMetadataSourceTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/expression/method/SecurityRules.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/intercept/AbstractSecurityInterceptorTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/intercept/AfterInvocationProviderManagerTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/intercept/InterceptorStatusTokenTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/intercept/NullRunAsManagerTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/intercept/RunAsImplAuthenticationProviderTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/intercept/RunAsManagerImplTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/intercept/RunAsUserTokenTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptorTests.java (99%) rename {core => access}/src/test/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisorTests.java (97%) rename {core => access}/src/test/java/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptorTests.java (99%) rename {core => access}/src/test/java/org/springframework/security/access/intercept/method/MapBasedMethodSecurityMetadataSourceTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/intercept/method/MethodInvocationPrivilegeEvaluatorTests.java (96%) rename {core => access}/src/test/java/org/springframework/security/access/intercept/method/MockMethodInvocation.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSourceTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/prepost/PostInvocationAdviceProviderTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoterTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/vote/AbstractAccessDecisionManagerTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/vote/AbstractAclVoterTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/vote/AffirmativeBasedTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/vote/AuthenticatedVoterTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/vote/ConsensusBasedTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/vote/DenyAgainVoter.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/vote/DenyVoter.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/vote/RoleHierarchyVoterTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/vote/RoleVoterTests.java (100%) rename {core => access}/src/test/java/org/springframework/security/access/vote/UnanimousBasedTests.java (100%) create mode 100644 core/src/test/java/org/springframework/security/authorization/method/BusinessService.java create mode 100644 core/src/test/java/org/springframework/security/authorization/method/MockMethodInvocation.java create mode 100644 core/src/test/java/org/springframework/security/authorization/method/RequireAdminRole.java create mode 100644 core/src/test/java/org/springframework/security/authorization/method/RequireUserRole.java create mode 100644 core/src/test/java/org/springframework/security/util/BusinessService.java create mode 100644 core/src/test/java/org/springframework/security/util/BusinessServiceImpl.java create mode 100644 core/src/test/java/org/springframework/security/util/Entity.java create mode 100644 core/src/test/java/org/springframework/security/util/RequireAdminRole.java create mode 100644 core/src/test/java/org/springframework/security/util/RequireUserRole.java diff --git a/access/spring-security-access.gradle b/access/spring-security-access.gradle new file mode 100644 index 0000000000..ff53b8d766 --- /dev/null +++ b/access/spring-security-access.gradle @@ -0,0 +1,42 @@ +apply plugin: 'io.spring.convention.spring-module' + +dependencies { + management platform(project(":spring-security-dependencies")) + api project(':spring-security-crypto') + api project(':spring-security-core') + api 'org.springframework:spring-aop' + api 'org.springframework:spring-beans' + api 'org.springframework:spring-context' + api 'org.springframework:spring-core' + api 'org.springframework:spring-expression' + api 'io.micrometer:micrometer-observation' + + optional 'com.fasterxml.jackson.core:jackson-databind' + optional 'io.micrometer:context-propagation' + optional 'io.projectreactor:reactor-core' + optional 'jakarta.annotation:jakarta.annotation-api' + optional 'org.aspectj:aspectjrt' + optional 'org.springframework:spring-jdbc' + optional 'org.springframework:spring-tx' + optional 'org.jetbrains.kotlinx:kotlinx-coroutines-reactor' + + testImplementation 'commons-collections:commons-collections' + testImplementation 'io.projectreactor:reactor-test' + testImplementation "org.assertj:assertj-core" + testImplementation "org.junit.jupiter:junit-jupiter-api" + testImplementation "org.junit.jupiter:junit-jupiter-params" + testImplementation "org.junit.jupiter:junit-jupiter-engine" + testImplementation "org.mockito:mockito-core" + testImplementation "org.mockito:mockito-junit-jupiter" + testImplementation "org.springframework:spring-core-test" + testImplementation "org.springframework:spring-test" + testImplementation 'org.skyscreamer:jsonassert' + testImplementation 'org.springframework:spring-test' + testImplementation 'org.jetbrains.kotlin:kotlin-reflect' + testImplementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8' + testImplementation 'io.mockk:mockk' + + testRuntimeOnly 'org.hsqldb:hsqldb' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' +} + diff --git a/core/src/main/java/org/springframework/security/access/AccessDecisionManager.java b/access/src/main/java/org/springframework/security/access/AccessDecisionManager.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/AccessDecisionManager.java rename to access/src/main/java/org/springframework/security/access/AccessDecisionManager.java diff --git a/core/src/main/java/org/springframework/security/access/AccessDecisionVoter.java b/access/src/main/java/org/springframework/security/access/AccessDecisionVoter.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/AccessDecisionVoter.java rename to access/src/main/java/org/springframework/security/access/AccessDecisionVoter.java diff --git a/core/src/main/java/org/springframework/security/access/AfterInvocationProvider.java b/access/src/main/java/org/springframework/security/access/AfterInvocationProvider.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/AfterInvocationProvider.java rename to access/src/main/java/org/springframework/security/access/AfterInvocationProvider.java diff --git a/core/src/main/java/org/springframework/security/access/ConfigAttribute.java b/access/src/main/java/org/springframework/security/access/ConfigAttribute.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/ConfigAttribute.java rename to access/src/main/java/org/springframework/security/access/ConfigAttribute.java diff --git a/core/src/main/java/org/springframework/security/access/SecurityConfig.java b/access/src/main/java/org/springframework/security/access/SecurityConfig.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/SecurityConfig.java rename to access/src/main/java/org/springframework/security/access/SecurityConfig.java diff --git a/core/src/main/java/org/springframework/security/access/SecurityMetadataSource.java b/access/src/main/java/org/springframework/security/access/SecurityMetadataSource.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/SecurityMetadataSource.java rename to access/src/main/java/org/springframework/security/access/SecurityMetadataSource.java diff --git a/core/src/main/java/org/springframework/security/access/annotation/AnnotationMetadataExtractor.java b/access/src/main/java/org/springframework/security/access/annotation/AnnotationMetadataExtractor.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/annotation/AnnotationMetadataExtractor.java rename to access/src/main/java/org/springframework/security/access/annotation/AnnotationMetadataExtractor.java diff --git a/core/src/main/java/org/springframework/security/access/annotation/Jsr250MethodSecurityMetadataSource.java b/access/src/main/java/org/springframework/security/access/annotation/Jsr250MethodSecurityMetadataSource.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/annotation/Jsr250MethodSecurityMetadataSource.java rename to access/src/main/java/org/springframework/security/access/annotation/Jsr250MethodSecurityMetadataSource.java diff --git a/core/src/main/java/org/springframework/security/access/annotation/Jsr250SecurityConfig.java b/access/src/main/java/org/springframework/security/access/annotation/Jsr250SecurityConfig.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/annotation/Jsr250SecurityConfig.java rename to access/src/main/java/org/springframework/security/access/annotation/Jsr250SecurityConfig.java diff --git a/core/src/main/java/org/springframework/security/access/annotation/Jsr250Voter.java b/access/src/main/java/org/springframework/security/access/annotation/Jsr250Voter.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/annotation/Jsr250Voter.java rename to access/src/main/java/org/springframework/security/access/annotation/Jsr250Voter.java diff --git a/core/src/main/java/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSource.java b/access/src/main/java/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSource.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSource.java rename to access/src/main/java/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSource.java diff --git a/access/src/main/java/org/springframework/security/access/annotation/package-info.java b/access/src/main/java/org/springframework/security/access/annotation/package-info.java new file mode 100644 index 0000000000..937a0b1c56 --- /dev/null +++ b/access/src/main/java/org/springframework/security/access/annotation/package-info.java @@ -0,0 +1,23 @@ +/* + * Copyright 2004-present 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Support for JSR-250 and Spring Security {@code @Secured} annotations. + */ +@NullMarked +package org.springframework.security.access.annotation; + +import org.jspecify.annotations.NullMarked; diff --git a/core/src/main/java/org/springframework/security/access/event/AbstractAuthorizationEvent.java b/access/src/main/java/org/springframework/security/access/event/AbstractAuthorizationEvent.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/event/AbstractAuthorizationEvent.java rename to access/src/main/java/org/springframework/security/access/event/AbstractAuthorizationEvent.java diff --git a/core/src/main/java/org/springframework/security/access/event/AuthenticationCredentialsNotFoundEvent.java b/access/src/main/java/org/springframework/security/access/event/AuthenticationCredentialsNotFoundEvent.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/event/AuthenticationCredentialsNotFoundEvent.java rename to access/src/main/java/org/springframework/security/access/event/AuthenticationCredentialsNotFoundEvent.java diff --git a/core/src/main/java/org/springframework/security/access/event/AuthorizationFailureEvent.java b/access/src/main/java/org/springframework/security/access/event/AuthorizationFailureEvent.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/event/AuthorizationFailureEvent.java rename to access/src/main/java/org/springframework/security/access/event/AuthorizationFailureEvent.java diff --git a/core/src/main/java/org/springframework/security/access/event/AuthorizedEvent.java b/access/src/main/java/org/springframework/security/access/event/AuthorizedEvent.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/event/AuthorizedEvent.java rename to access/src/main/java/org/springframework/security/access/event/AuthorizedEvent.java diff --git a/core/src/main/java/org/springframework/security/access/event/LoggerListener.java b/access/src/main/java/org/springframework/security/access/event/LoggerListener.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/event/LoggerListener.java rename to access/src/main/java/org/springframework/security/access/event/LoggerListener.java diff --git a/core/src/main/java/org/springframework/security/access/event/PublicInvocationEvent.java b/access/src/main/java/org/springframework/security/access/event/PublicInvocationEvent.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/event/PublicInvocationEvent.java rename to access/src/main/java/org/springframework/security/access/event/PublicInvocationEvent.java diff --git a/core/src/main/java/org/springframework/security/access/event/package-info.java b/access/src/main/java/org/springframework/security/access/event/package-info.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/event/package-info.java rename to access/src/main/java/org/springframework/security/access/event/package-info.java diff --git a/core/src/main/java/org/springframework/security/access/expression/method/AbstractExpressionBasedMethodConfigAttribute.java b/access/src/main/java/org/springframework/security/access/expression/method/AbstractExpressionBasedMethodConfigAttribute.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/expression/method/AbstractExpressionBasedMethodConfigAttribute.java rename to access/src/main/java/org/springframework/security/access/expression/method/AbstractExpressionBasedMethodConfigAttribute.java diff --git a/core/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedAnnotationAttributeFactory.java b/access/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedAnnotationAttributeFactory.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedAnnotationAttributeFactory.java rename to access/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedAnnotationAttributeFactory.java diff --git a/core/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedPostInvocationAdvice.java b/access/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedPostInvocationAdvice.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedPostInvocationAdvice.java rename to access/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedPostInvocationAdvice.java diff --git a/core/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdvice.java b/access/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdvice.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdvice.java rename to access/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdvice.java diff --git a/core/src/main/java/org/springframework/security/access/expression/method/PostInvocationExpressionAttribute.java b/access/src/main/java/org/springframework/security/access/expression/method/PostInvocationExpressionAttribute.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/expression/method/PostInvocationExpressionAttribute.java rename to access/src/main/java/org/springframework/security/access/expression/method/PostInvocationExpressionAttribute.java diff --git a/core/src/main/java/org/springframework/security/access/expression/method/PreInvocationExpressionAttribute.java b/access/src/main/java/org/springframework/security/access/expression/method/PreInvocationExpressionAttribute.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/expression/method/PreInvocationExpressionAttribute.java rename to access/src/main/java/org/springframework/security/access/expression/method/PreInvocationExpressionAttribute.java diff --git a/access/src/main/java/org/springframework/security/access/expression/method/package-info.java b/access/src/main/java/org/springframework/security/access/expression/method/package-info.java new file mode 100644 index 0000000000..0923fe65a6 --- /dev/null +++ b/access/src/main/java/org/springframework/security/access/expression/method/package-info.java @@ -0,0 +1,25 @@ +/* + * Copyright 2004-present 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Implementation of expression-based method security. + * + * @since 3.0 + */ +@NullMarked +package org.springframework.security.access.expression.method; + +import org.jspecify.annotations.NullMarked; diff --git a/core/src/main/java/org/springframework/security/access/intercept/AbstractSecurityInterceptor.java b/access/src/main/java/org/springframework/security/access/intercept/AbstractSecurityInterceptor.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/intercept/AbstractSecurityInterceptor.java rename to access/src/main/java/org/springframework/security/access/intercept/AbstractSecurityInterceptor.java diff --git a/core/src/main/java/org/springframework/security/access/intercept/AfterInvocationManager.java b/access/src/main/java/org/springframework/security/access/intercept/AfterInvocationManager.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/intercept/AfterInvocationManager.java rename to access/src/main/java/org/springframework/security/access/intercept/AfterInvocationManager.java diff --git a/core/src/main/java/org/springframework/security/access/intercept/AfterInvocationProviderManager.java b/access/src/main/java/org/springframework/security/access/intercept/AfterInvocationProviderManager.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/intercept/AfterInvocationProviderManager.java rename to access/src/main/java/org/springframework/security/access/intercept/AfterInvocationProviderManager.java diff --git a/core/src/main/java/org/springframework/security/access/intercept/InterceptorStatusToken.java b/access/src/main/java/org/springframework/security/access/intercept/InterceptorStatusToken.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/intercept/InterceptorStatusToken.java rename to access/src/main/java/org/springframework/security/access/intercept/InterceptorStatusToken.java diff --git a/core/src/main/java/org/springframework/security/access/intercept/MethodInvocationPrivilegeEvaluator.java b/access/src/main/java/org/springframework/security/access/intercept/MethodInvocationPrivilegeEvaluator.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/intercept/MethodInvocationPrivilegeEvaluator.java rename to access/src/main/java/org/springframework/security/access/intercept/MethodInvocationPrivilegeEvaluator.java diff --git a/core/src/main/java/org/springframework/security/access/intercept/NullRunAsManager.java b/access/src/main/java/org/springframework/security/access/intercept/NullRunAsManager.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/intercept/NullRunAsManager.java rename to access/src/main/java/org/springframework/security/access/intercept/NullRunAsManager.java diff --git a/core/src/main/java/org/springframework/security/access/intercept/RunAsImplAuthenticationProvider.java b/access/src/main/java/org/springframework/security/access/intercept/RunAsImplAuthenticationProvider.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/intercept/RunAsImplAuthenticationProvider.java rename to access/src/main/java/org/springframework/security/access/intercept/RunAsImplAuthenticationProvider.java diff --git a/core/src/main/java/org/springframework/security/access/intercept/RunAsManager.java b/access/src/main/java/org/springframework/security/access/intercept/RunAsManager.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/intercept/RunAsManager.java rename to access/src/main/java/org/springframework/security/access/intercept/RunAsManager.java diff --git a/core/src/main/java/org/springframework/security/access/intercept/RunAsManagerImpl.java b/access/src/main/java/org/springframework/security/access/intercept/RunAsManagerImpl.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/intercept/RunAsManagerImpl.java rename to access/src/main/java/org/springframework/security/access/intercept/RunAsManagerImpl.java diff --git a/core/src/main/java/org/springframework/security/access/intercept/RunAsUserToken.java b/access/src/main/java/org/springframework/security/access/intercept/RunAsUserToken.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/intercept/RunAsUserToken.java rename to access/src/main/java/org/springframework/security/access/intercept/RunAsUserToken.java diff --git a/core/src/main/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptor.java b/access/src/main/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptor.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptor.java rename to access/src/main/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptor.java diff --git a/core/src/main/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisor.java b/access/src/main/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisor.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisor.java rename to access/src/main/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisor.java diff --git a/core/src/main/java/org/springframework/security/access/intercept/aopalliance/package-info.java b/access/src/main/java/org/springframework/security/access/intercept/aopalliance/package-info.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/intercept/aopalliance/package-info.java rename to access/src/main/java/org/springframework/security/access/intercept/aopalliance/package-info.java diff --git a/core/src/main/java/org/springframework/security/access/intercept/aspectj/AspectJCallback.java b/access/src/main/java/org/springframework/security/access/intercept/aspectj/AspectJCallback.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/intercept/aspectj/AspectJCallback.java rename to access/src/main/java/org/springframework/security/access/intercept/aspectj/AspectJCallback.java diff --git a/core/src/main/java/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptor.java b/access/src/main/java/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptor.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptor.java rename to access/src/main/java/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptor.java diff --git a/core/src/main/java/org/springframework/security/access/intercept/aspectj/MethodInvocationAdapter.java b/access/src/main/java/org/springframework/security/access/intercept/aspectj/MethodInvocationAdapter.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/intercept/aspectj/MethodInvocationAdapter.java rename to access/src/main/java/org/springframework/security/access/intercept/aspectj/MethodInvocationAdapter.java diff --git a/core/src/main/java/org/springframework/security/access/intercept/aspectj/package-info.java b/access/src/main/java/org/springframework/security/access/intercept/aspectj/package-info.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/intercept/aspectj/package-info.java rename to access/src/main/java/org/springframework/security/access/intercept/aspectj/package-info.java diff --git a/core/src/main/java/org/springframework/security/access/intercept/package-info.java b/access/src/main/java/org/springframework/security/access/intercept/package-info.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/intercept/package-info.java rename to access/src/main/java/org/springframework/security/access/intercept/package-info.java diff --git a/core/src/main/java/org/springframework/security/access/method/AbstractFallbackMethodSecurityMetadataSource.java b/access/src/main/java/org/springframework/security/access/method/AbstractFallbackMethodSecurityMetadataSource.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/method/AbstractFallbackMethodSecurityMetadataSource.java rename to access/src/main/java/org/springframework/security/access/method/AbstractFallbackMethodSecurityMetadataSource.java diff --git a/core/src/main/java/org/springframework/security/access/method/AbstractMethodSecurityMetadataSource.java b/access/src/main/java/org/springframework/security/access/method/AbstractMethodSecurityMetadataSource.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/method/AbstractMethodSecurityMetadataSource.java rename to access/src/main/java/org/springframework/security/access/method/AbstractMethodSecurityMetadataSource.java diff --git a/core/src/main/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSource.java b/access/src/main/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSource.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSource.java rename to access/src/main/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSource.java diff --git a/core/src/main/java/org/springframework/security/access/method/MapBasedMethodSecurityMetadataSource.java b/access/src/main/java/org/springframework/security/access/method/MapBasedMethodSecurityMetadataSource.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/method/MapBasedMethodSecurityMetadataSource.java rename to access/src/main/java/org/springframework/security/access/method/MapBasedMethodSecurityMetadataSource.java diff --git a/core/src/main/java/org/springframework/security/access/method/MethodSecurityMetadataSource.java b/access/src/main/java/org/springframework/security/access/method/MethodSecurityMetadataSource.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/method/MethodSecurityMetadataSource.java rename to access/src/main/java/org/springframework/security/access/method/MethodSecurityMetadataSource.java diff --git a/core/src/main/java/org/springframework/security/access/method/P.java b/access/src/main/java/org/springframework/security/access/method/P.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/method/P.java rename to access/src/main/java/org/springframework/security/access/method/P.java diff --git a/core/src/main/java/org/springframework/security/access/method/package-info.java b/access/src/main/java/org/springframework/security/access/method/package-info.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/method/package-info.java rename to access/src/main/java/org/springframework/security/access/method/package-info.java diff --git a/access/src/main/java/org/springframework/security/access/package-info.java b/access/src/main/java/org/springframework/security/access/package-info.java new file mode 100644 index 0000000000..01ac014fe7 --- /dev/null +++ b/access/src/main/java/org/springframework/security/access/package-info.java @@ -0,0 +1,27 @@ +/* + * Copyright 2004-present 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Core access-control related code, including security metadata related classes, + * interception code, access control annotations, EL support and voter-based + * implementations of the central + * {@link org.springframework.security.access.AccessDecisionManager AccessDecisionManager} + * interface. + */ +@NullMarked +package org.springframework.security.access; + +import org.jspecify.annotations.NullMarked; diff --git a/core/src/main/java/org/springframework/security/access/prepost/PostInvocationAdviceProvider.java b/access/src/main/java/org/springframework/security/access/prepost/PostInvocationAdviceProvider.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/prepost/PostInvocationAdviceProvider.java rename to access/src/main/java/org/springframework/security/access/prepost/PostInvocationAdviceProvider.java diff --git a/core/src/main/java/org/springframework/security/access/prepost/PostInvocationAttribute.java b/access/src/main/java/org/springframework/security/access/prepost/PostInvocationAttribute.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/prepost/PostInvocationAttribute.java rename to access/src/main/java/org/springframework/security/access/prepost/PostInvocationAttribute.java diff --git a/core/src/main/java/org/springframework/security/access/prepost/PostInvocationAuthorizationAdvice.java b/access/src/main/java/org/springframework/security/access/prepost/PostInvocationAuthorizationAdvice.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/prepost/PostInvocationAuthorizationAdvice.java rename to access/src/main/java/org/springframework/security/access/prepost/PostInvocationAuthorizationAdvice.java diff --git a/core/src/main/java/org/springframework/security/access/prepost/PreInvocationAttribute.java b/access/src/main/java/org/springframework/security/access/prepost/PreInvocationAttribute.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/prepost/PreInvocationAttribute.java rename to access/src/main/java/org/springframework/security/access/prepost/PreInvocationAttribute.java diff --git a/core/src/main/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdvice.java b/access/src/main/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdvice.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdvice.java rename to access/src/main/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdvice.java diff --git a/core/src/main/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoter.java b/access/src/main/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoter.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoter.java rename to access/src/main/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoter.java diff --git a/core/src/main/java/org/springframework/security/access/prepost/PrePostAdviceReactiveMethodInterceptor.java b/access/src/main/java/org/springframework/security/access/prepost/PrePostAdviceReactiveMethodInterceptor.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/prepost/PrePostAdviceReactiveMethodInterceptor.java rename to access/src/main/java/org/springframework/security/access/prepost/PrePostAdviceReactiveMethodInterceptor.java diff --git a/core/src/main/java/org/springframework/security/access/prepost/PrePostAnnotationSecurityMetadataSource.java b/access/src/main/java/org/springframework/security/access/prepost/PrePostAnnotationSecurityMetadataSource.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/prepost/PrePostAnnotationSecurityMetadataSource.java rename to access/src/main/java/org/springframework/security/access/prepost/PrePostAnnotationSecurityMetadataSource.java diff --git a/core/src/main/java/org/springframework/security/access/prepost/PrePostInvocationAttributeFactory.java b/access/src/main/java/org/springframework/security/access/prepost/PrePostInvocationAttributeFactory.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/prepost/PrePostInvocationAttributeFactory.java rename to access/src/main/java/org/springframework/security/access/prepost/PrePostInvocationAttributeFactory.java diff --git a/access/src/main/java/org/springframework/security/access/prepost/package-info.java b/access/src/main/java/org/springframework/security/access/prepost/package-info.java new file mode 100644 index 0000000000..d4322df1a4 --- /dev/null +++ b/access/src/main/java/org/springframework/security/access/prepost/package-info.java @@ -0,0 +1,27 @@ +/* + * Copyright 2004-present 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Contains the infrastructure classes for handling the {@code @PreAuthorize}, + * {@code @PreFilter}, {@code @PostAuthorize} and {@code @PostFilter} annotations. + *

+ * Other than the annotations themselves, the classes should be regarded as for internal + * framework use and are liable to change without notice. + */ +@NullMarked +package org.springframework.security.access.prepost; + +import org.jspecify.annotations.NullMarked; diff --git a/core/src/main/java/org/springframework/security/access/vote/AbstractAccessDecisionManager.java b/access/src/main/java/org/springframework/security/access/vote/AbstractAccessDecisionManager.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/vote/AbstractAccessDecisionManager.java rename to access/src/main/java/org/springframework/security/access/vote/AbstractAccessDecisionManager.java diff --git a/core/src/main/java/org/springframework/security/access/vote/AbstractAclVoter.java b/access/src/main/java/org/springframework/security/access/vote/AbstractAclVoter.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/vote/AbstractAclVoter.java rename to access/src/main/java/org/springframework/security/access/vote/AbstractAclVoter.java diff --git a/core/src/main/java/org/springframework/security/access/vote/AffirmativeBased.java b/access/src/main/java/org/springframework/security/access/vote/AffirmativeBased.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/vote/AffirmativeBased.java rename to access/src/main/java/org/springframework/security/access/vote/AffirmativeBased.java diff --git a/core/src/main/java/org/springframework/security/access/vote/AuthenticatedVoter.java b/access/src/main/java/org/springframework/security/access/vote/AuthenticatedVoter.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/vote/AuthenticatedVoter.java rename to access/src/main/java/org/springframework/security/access/vote/AuthenticatedVoter.java diff --git a/core/src/main/java/org/springframework/security/access/vote/ConsensusBased.java b/access/src/main/java/org/springframework/security/access/vote/ConsensusBased.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/vote/ConsensusBased.java rename to access/src/main/java/org/springframework/security/access/vote/ConsensusBased.java diff --git a/core/src/main/java/org/springframework/security/access/vote/RoleHierarchyVoter.java b/access/src/main/java/org/springframework/security/access/vote/RoleHierarchyVoter.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/vote/RoleHierarchyVoter.java rename to access/src/main/java/org/springframework/security/access/vote/RoleHierarchyVoter.java diff --git a/core/src/main/java/org/springframework/security/access/vote/RoleVoter.java b/access/src/main/java/org/springframework/security/access/vote/RoleVoter.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/vote/RoleVoter.java rename to access/src/main/java/org/springframework/security/access/vote/RoleVoter.java diff --git a/core/src/main/java/org/springframework/security/access/vote/UnanimousBased.java b/access/src/main/java/org/springframework/security/access/vote/UnanimousBased.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/vote/UnanimousBased.java rename to access/src/main/java/org/springframework/security/access/vote/UnanimousBased.java diff --git a/core/src/main/java/org/springframework/security/access/vote/package-info.java b/access/src/main/java/org/springframework/security/access/vote/package-info.java similarity index 100% rename from core/src/main/java/org/springframework/security/access/vote/package-info.java rename to access/src/main/java/org/springframework/security/access/vote/package-info.java diff --git a/core/src/test/java/org/springframework/security/access/AuthenticationCredentialsNotFoundEventTests.java b/access/src/test/java/org/springframework/security/access/AuthenticationCredentialsNotFoundEventTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/AuthenticationCredentialsNotFoundEventTests.java rename to access/src/test/java/org/springframework/security/access/AuthenticationCredentialsNotFoundEventTests.java diff --git a/core/src/test/java/org/springframework/security/access/AuthorizationFailureEventTests.java b/access/src/test/java/org/springframework/security/access/AuthorizationFailureEventTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/AuthorizationFailureEventTests.java rename to access/src/test/java/org/springframework/security/access/AuthorizationFailureEventTests.java diff --git a/core/src/test/java/org/springframework/security/access/AuthorizedEventTests.java b/access/src/test/java/org/springframework/security/access/AuthorizedEventTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/AuthorizedEventTests.java rename to access/src/test/java/org/springframework/security/access/AuthorizedEventTests.java diff --git a/access/src/test/java/org/springframework/security/access/ITargetObject.java b/access/src/test/java/org/springframework/security/access/ITargetObject.java new file mode 100644 index 0000000000..9929eb53ba --- /dev/null +++ b/access/src/test/java/org/springframework/security/access/ITargetObject.java @@ -0,0 +1,36 @@ +/* + * Copyright 2004, 2005, 2006 Acegi Technology Pty Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.access; + +/** + * Represents the interface of a secured object. + * + * @author Ben Alex + */ +public interface ITargetObject { + + Integer computeHashCode(String input); + + int countLength(String input); + + String makeLowerCase(String input); + + String makeUpperCase(String input); + + String publicMakeLowerCase(String input); + +} diff --git a/access/src/test/java/org/springframework/security/access/OtherTargetObject.java b/access/src/test/java/org/springframework/security/access/OtherTargetObject.java new file mode 100644 index 0000000000..c4ea9a2fb3 --- /dev/null +++ b/access/src/test/java/org/springframework/security/access/OtherTargetObject.java @@ -0,0 +1,53 @@ +/* + * Copyright 2004, 2005, 2006 Acegi Technology Pty Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.access; + +/** + * Simply extends {@link TargetObject} so we have a different object to put configuration + * attributes against. + *

+ * There is no different behaviour. We have to define each method so that + * Class.getMethod(methodName, args) returns a Method + * referencing this class rather than the parent class. + *

+ *

+ * We need to implement ITargetObject again because the + * MethodDefinitionAttributes only locates attributes on interfaces + * explicitly defined by the intercepted class (not the interfaces defined by its parent + * class or classes). + *

+ * + * @author Ben Alex + */ +public class OtherTargetObject extends TargetObject implements ITargetObject { + + @Override + public String makeLowerCase(String input) { + return super.makeLowerCase(input); + } + + @Override + public String makeUpperCase(String input) { + return super.makeUpperCase(input); + } + + @Override + public String publicMakeLowerCase(String input) { + return super.publicMakeLowerCase(input); + } + +} diff --git a/core/src/test/java/org/springframework/security/access/SecurityConfigTests.java b/access/src/test/java/org/springframework/security/access/SecurityConfigTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/SecurityConfigTests.java rename to access/src/test/java/org/springframework/security/access/SecurityConfigTests.java diff --git a/access/src/test/java/org/springframework/security/access/TargetObject.java b/access/src/test/java/org/springframework/security/access/TargetObject.java new file mode 100644 index 0000000000..7af0aff10d --- /dev/null +++ b/access/src/test/java/org/springframework/security/access/TargetObject.java @@ -0,0 +1,81 @@ +/* + * Copyright 2004, 2005, 2006 Acegi Technology Pty Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.access; + +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; + +/** + * Represents a secured object. + * + * @author Ben Alex + */ +public class TargetObject implements ITargetObject { + + @Override + public Integer computeHashCode(String input) { + return input.hashCode(); + } + + @Override + public int countLength(String input) { + return input.length(); + } + + /** + * Returns the lowercase string, followed by security environment information. + * @param input the message to make lowercase + * @return the lowercase message, a space, the Authentication class that + * was on the SecurityContext at the time of method invocation, and a + * boolean indicating if the Authentication object is authenticated or + * not + */ + @Override + public String makeLowerCase(String input) { + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + if (auth == null) { + return input.toLowerCase() + " Authentication empty"; + } + else { + return input.toLowerCase() + " " + auth.getClass().getName() + " " + auth.isAuthenticated(); + } + } + + /** + * Returns the uppercase string, followed by security environment information. + * @param input the message to make uppercase + * @return the uppercase message, a space, the Authentication class that + * was on the SecurityContext at the time of method invocation, and a + * boolean indicating if the Authentication object is authenticated or + * not + */ + @Override + public String makeUpperCase(String input) { + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + return input.toUpperCase() + " " + auth.getClass().getName() + " " + auth.isAuthenticated(); + } + + /** + * Delegates through to the {@link #makeLowerCase(String)} method. + * @param input the message to be made lower-case + */ + @Override + public String publicMakeLowerCase(String input) { + return this.makeLowerCase(input); + } + +} diff --git a/core/src/test/java/org/springframework/security/access/annotation/BusinessService.java b/access/src/test/java/org/springframework/security/access/annotation/BusinessService.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/annotation/BusinessService.java rename to access/src/test/java/org/springframework/security/access/annotation/BusinessService.java diff --git a/core/src/test/java/org/springframework/security/access/annotation/BusinessServiceImpl.java b/access/src/test/java/org/springframework/security/access/annotation/BusinessServiceImpl.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/annotation/BusinessServiceImpl.java rename to access/src/test/java/org/springframework/security/access/annotation/BusinessServiceImpl.java diff --git a/core/src/test/java/org/springframework/security/access/annotation/Entity.java b/access/src/test/java/org/springframework/security/access/annotation/Entity.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/annotation/Entity.java rename to access/src/test/java/org/springframework/security/access/annotation/Entity.java diff --git a/core/src/test/java/org/springframework/security/access/annotation/ExpressionProtectedBusinessServiceImpl.java b/access/src/test/java/org/springframework/security/access/annotation/ExpressionProtectedBusinessServiceImpl.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/annotation/ExpressionProtectedBusinessServiceImpl.java rename to access/src/test/java/org/springframework/security/access/annotation/ExpressionProtectedBusinessServiceImpl.java diff --git a/core/src/test/java/org/springframework/security/access/annotation/Jsr250BusinessServiceImpl.java b/access/src/test/java/org/springframework/security/access/annotation/Jsr250BusinessServiceImpl.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/annotation/Jsr250BusinessServiceImpl.java rename to access/src/test/java/org/springframework/security/access/annotation/Jsr250BusinessServiceImpl.java diff --git a/core/src/test/java/org/springframework/security/access/annotation/Jsr250MethodSecurityMetadataSourceTests.java b/access/src/test/java/org/springframework/security/access/annotation/Jsr250MethodSecurityMetadataSourceTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/annotation/Jsr250MethodSecurityMetadataSourceTests.java rename to access/src/test/java/org/springframework/security/access/annotation/Jsr250MethodSecurityMetadataSourceTests.java diff --git a/core/src/test/java/org/springframework/security/access/annotation/Jsr250VoterTests.java b/access/src/test/java/org/springframework/security/access/annotation/Jsr250VoterTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/annotation/Jsr250VoterTests.java rename to access/src/test/java/org/springframework/security/access/annotation/Jsr250VoterTests.java diff --git a/core/src/test/java/org/springframework/security/access/annotation/RequireAdminRole.java b/access/src/test/java/org/springframework/security/access/annotation/RequireAdminRole.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/annotation/RequireAdminRole.java rename to access/src/test/java/org/springframework/security/access/annotation/RequireAdminRole.java diff --git a/core/src/test/java/org/springframework/security/access/annotation/RequireUserRole.java b/access/src/test/java/org/springframework/security/access/annotation/RequireUserRole.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/annotation/RequireUserRole.java rename to access/src/test/java/org/springframework/security/access/annotation/RequireUserRole.java diff --git a/core/src/test/java/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSourceTests.java b/access/src/test/java/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSourceTests.java similarity index 98% rename from core/src/test/java/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSourceTests.java rename to access/src/test/java/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSourceTests.java index 71d96ed75a..e4b5235f16 100644 --- a/core/src/test/java/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSourceTests.java +++ b/access/src/test/java/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSourceTests.java @@ -39,8 +39,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; /** - * Tests for - * {@link org.springframework.security.access.annotation.SecuredAnnotationSecurityMetadataSource} + * Tests for {@link SecuredAnnotationSecurityMetadataSource} * * @author Mark St.Godard * @author Joe Scalise diff --git a/core/src/test/java/org/springframework/security/access/annotation/sec2150/CrudRepository.java b/access/src/test/java/org/springframework/security/access/annotation/sec2150/CrudRepository.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/annotation/sec2150/CrudRepository.java rename to access/src/test/java/org/springframework/security/access/annotation/sec2150/CrudRepository.java diff --git a/core/src/test/java/org/springframework/security/access/annotation/sec2150/MethodInvocationFactory.java b/access/src/test/java/org/springframework/security/access/annotation/sec2150/MethodInvocationFactory.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/annotation/sec2150/MethodInvocationFactory.java rename to access/src/test/java/org/springframework/security/access/annotation/sec2150/MethodInvocationFactory.java diff --git a/core/src/test/java/org/springframework/security/access/annotation/sec2150/PersonRepository.java b/access/src/test/java/org/springframework/security/access/annotation/sec2150/PersonRepository.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/annotation/sec2150/PersonRepository.java rename to access/src/test/java/org/springframework/security/access/annotation/sec2150/PersonRepository.java diff --git a/core/src/test/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandlerTests.java b/access/src/test/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandlerTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandlerTests.java rename to access/src/test/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandlerTests.java diff --git a/core/src/test/java/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdviceTests.java b/access/src/test/java/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdviceTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdviceTests.java rename to access/src/test/java/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdviceTests.java diff --git a/core/src/test/java/org/springframework/security/access/expression/method/MethodExpressionVoterTests.java b/access/src/test/java/org/springframework/security/access/expression/method/MethodExpressionVoterTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/expression/method/MethodExpressionVoterTests.java rename to access/src/test/java/org/springframework/security/access/expression/method/MethodExpressionVoterTests.java diff --git a/core/src/test/java/org/springframework/security/access/expression/method/MethodSecurityEvaluationContextTests.java b/access/src/test/java/org/springframework/security/access/expression/method/MethodSecurityEvaluationContextTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/expression/method/MethodSecurityEvaluationContextTests.java rename to access/src/test/java/org/springframework/security/access/expression/method/MethodSecurityEvaluationContextTests.java diff --git a/core/src/test/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRootTests.java b/access/src/test/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRootTests.java similarity index 84% rename from core/src/test/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRootTests.java rename to access/src/test/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRootTests.java index 6f65547e91..a908236c99 100644 --- a/core/src/test/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRootTests.java +++ b/access/src/test/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRootTests.java @@ -17,6 +17,7 @@ package org.springframework.security.access.expression.method; import org.aopalliance.intercept.MethodInvocation; +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -28,7 +29,6 @@ import org.springframework.security.access.expression.ExpressionUtils; import org.springframework.security.authentication.AuthenticationTrustResolver; import org.springframework.security.core.Authentication; -import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.given; @@ -65,19 +65,19 @@ public class MethodSecurityExpressionRootTests { public void canCallMethodsOnVariables() { this.ctx.setVariable("var", "somestring"); Expression e = this.parser.parseExpression("#var.length() == 10"); - assertThat(ExpressionUtils.evaluateAsBoolean(e, this.ctx)).isTrue(); + Assertions.assertThat(ExpressionUtils.evaluateAsBoolean(e, this.ctx)).isTrue(); } @Test public void isAnonymousReturnsTrueIfTrustResolverReportsAnonymous() { given(this.trustResolver.isAnonymous(this.user)).willReturn(true); - assertThat(this.root.isAnonymous()).isTrue(); + Assertions.assertThat(this.root.isAnonymous()).isTrue(); } @Test public void isAnonymousReturnsFalseIfTrustResolverReportsNonAnonymous() { given(this.trustResolver.isAnonymous(this.user)).willReturn(false); - assertThat(this.root.isAnonymous()).isFalse(); + Assertions.assertThat(this.root.isAnonymous()).isFalse(); } @Test @@ -87,7 +87,7 @@ public class MethodSecurityExpressionRootTests { this.ctx.setVariable("domainObject", dummyDomainObject); this.root.setPermissionEvaluator(pe); given(pe.hasPermission(this.user, dummyDomainObject, "ignored")).willReturn(false); - assertThat(this.root.hasPermission(dummyDomainObject, "ignored")).isFalse(); + Assertions.assertThat(this.root.hasPermission(dummyDomainObject, "ignored")).isFalse(); } @Test @@ -97,7 +97,7 @@ public class MethodSecurityExpressionRootTests { this.ctx.setVariable("domainObject", dummyDomainObject); this.root.setPermissionEvaluator(pe); given(pe.hasPermission(this.user, dummyDomainObject, "ignored")).willReturn(true); - assertThat(this.root.hasPermission(dummyDomainObject, "ignored")).isTrue(); + Assertions.assertThat(this.root.hasPermission(dummyDomainObject, "ignored")).isTrue(); } @Test @@ -109,13 +109,13 @@ public class MethodSecurityExpressionRootTests { given(pe.hasPermission(eq(this.user), eq(dummyDomainObject), any(Integer.class))).willReturn(true, true, false); Expression e = this.parser.parseExpression("hasPermission(#domainObject, 0xA)"); // evaluator returns true - assertThat(ExpressionUtils.evaluateAsBoolean(e, this.ctx)).isTrue(); + Assertions.assertThat(ExpressionUtils.evaluateAsBoolean(e, this.ctx)).isTrue(); e = this.parser.parseExpression("hasPermission(#domainObject, 10)"); // evaluator returns true - assertThat(ExpressionUtils.evaluateAsBoolean(e, this.ctx)).isTrue(); + Assertions.assertThat(ExpressionUtils.evaluateAsBoolean(e, this.ctx)).isTrue(); e = this.parser.parseExpression("hasPermission(#domainObject, 0xFF)"); // evaluator returns false, make sure return value matches - assertThat(ExpressionUtils.evaluateAsBoolean(e, this.ctx)).isFalse(); + Assertions.assertThat(ExpressionUtils.evaluateAsBoolean(e, this.ctx)).isFalse(); } @Test @@ -132,11 +132,11 @@ public class MethodSecurityExpressionRootTests { given(pe.hasPermission(this.user, targetObject, i)).willReturn(true, false); given(pe.hasPermission(this.user, "x", i)).willReturn(true); Expression e = this.parser.parseExpression("hasPermission(this, 2)"); - assertThat(ExpressionUtils.evaluateAsBoolean(e, this.ctx)).isTrue(); + Assertions.assertThat(ExpressionUtils.evaluateAsBoolean(e, this.ctx)).isTrue(); e = this.parser.parseExpression("hasPermission(this, 2)"); - assertThat(ExpressionUtils.evaluateAsBoolean(e, this.ctx)).isFalse(); + Assertions.assertThat(ExpressionUtils.evaluateAsBoolean(e, this.ctx)).isFalse(); e = this.parser.parseExpression("hasPermission(this.x, 2)"); - assertThat(ExpressionUtils.evaluateAsBoolean(e, this.ctx)).isTrue(); + Assertions.assertThat(ExpressionUtils.evaluateAsBoolean(e, this.ctx)).isTrue(); } } diff --git a/core/src/test/java/org/springframework/security/access/expression/method/PrePostAnnotationSecurityMetadataSourceTests.java b/access/src/test/java/org/springframework/security/access/expression/method/PrePostAnnotationSecurityMetadataSourceTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/expression/method/PrePostAnnotationSecurityMetadataSourceTests.java rename to access/src/test/java/org/springframework/security/access/expression/method/PrePostAnnotationSecurityMetadataSourceTests.java diff --git a/core/src/test/java/org/springframework/security/access/expression/method/SecurityRules.java b/access/src/test/java/org/springframework/security/access/expression/method/SecurityRules.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/expression/method/SecurityRules.java rename to access/src/test/java/org/springframework/security/access/expression/method/SecurityRules.java diff --git a/core/src/test/java/org/springframework/security/access/intercept/AbstractSecurityInterceptorTests.java b/access/src/test/java/org/springframework/security/access/intercept/AbstractSecurityInterceptorTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/intercept/AbstractSecurityInterceptorTests.java rename to access/src/test/java/org/springframework/security/access/intercept/AbstractSecurityInterceptorTests.java diff --git a/core/src/test/java/org/springframework/security/access/intercept/AfterInvocationProviderManagerTests.java b/access/src/test/java/org/springframework/security/access/intercept/AfterInvocationProviderManagerTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/intercept/AfterInvocationProviderManagerTests.java rename to access/src/test/java/org/springframework/security/access/intercept/AfterInvocationProviderManagerTests.java diff --git a/core/src/test/java/org/springframework/security/access/intercept/InterceptorStatusTokenTests.java b/access/src/test/java/org/springframework/security/access/intercept/InterceptorStatusTokenTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/intercept/InterceptorStatusTokenTests.java rename to access/src/test/java/org/springframework/security/access/intercept/InterceptorStatusTokenTests.java diff --git a/core/src/test/java/org/springframework/security/access/intercept/NullRunAsManagerTests.java b/access/src/test/java/org/springframework/security/access/intercept/NullRunAsManagerTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/intercept/NullRunAsManagerTests.java rename to access/src/test/java/org/springframework/security/access/intercept/NullRunAsManagerTests.java diff --git a/core/src/test/java/org/springframework/security/access/intercept/RunAsImplAuthenticationProviderTests.java b/access/src/test/java/org/springframework/security/access/intercept/RunAsImplAuthenticationProviderTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/intercept/RunAsImplAuthenticationProviderTests.java rename to access/src/test/java/org/springframework/security/access/intercept/RunAsImplAuthenticationProviderTests.java diff --git a/core/src/test/java/org/springframework/security/access/intercept/RunAsManagerImplTests.java b/access/src/test/java/org/springframework/security/access/intercept/RunAsManagerImplTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/intercept/RunAsManagerImplTests.java rename to access/src/test/java/org/springframework/security/access/intercept/RunAsManagerImplTests.java diff --git a/core/src/test/java/org/springframework/security/access/intercept/RunAsUserTokenTests.java b/access/src/test/java/org/springframework/security/access/intercept/RunAsUserTokenTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/intercept/RunAsUserTokenTests.java rename to access/src/test/java/org/springframework/security/access/intercept/RunAsUserTokenTests.java diff --git a/core/src/test/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptorTests.java b/access/src/test/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptorTests.java similarity index 99% rename from core/src/test/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptorTests.java rename to access/src/test/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptorTests.java index a120f7eb63..9b0ca1577d 100644 --- a/core/src/test/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptorTests.java +++ b/access/src/test/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptorTests.java @@ -25,12 +25,12 @@ import org.junit.jupiter.api.Test; import org.springframework.aop.framework.ProxyFactory; import org.springframework.context.ApplicationEventPublisher; -import org.springframework.security.ITargetObject; -import org.springframework.security.TargetObject; import org.springframework.security.access.AccessDecisionManager; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.ConfigAttribute; +import org.springframework.security.access.ITargetObject; import org.springframework.security.access.SecurityConfig; +import org.springframework.security.access.TargetObject; import org.springframework.security.access.event.AuthorizationFailureEvent; import org.springframework.security.access.event.AuthorizedEvent; import org.springframework.security.access.intercept.AfterInvocationManager; diff --git a/core/src/test/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisorTests.java b/access/src/test/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisorTests.java similarity index 97% rename from core/src/test/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisorTests.java rename to access/src/test/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisorTests.java index 60c95f8cbb..b8e314e423 100644 --- a/core/src/test/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisorTests.java +++ b/access/src/test/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisorTests.java @@ -20,8 +20,8 @@ import java.lang.reflect.Method; import org.junit.jupiter.api.Test; -import org.springframework.security.TargetObject; import org.springframework.security.access.SecurityConfig; +import org.springframework.security.access.TargetObject; import org.springframework.security.access.method.MethodSecurityMetadataSource; import static org.assertj.core.api.Assertions.assertThat; diff --git a/core/src/test/java/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptorTests.java b/access/src/test/java/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptorTests.java similarity index 99% rename from core/src/test/java/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptorTests.java rename to access/src/test/java/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptorTests.java index 4afe87616d..0c80f07e77 100644 --- a/core/src/test/java/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptorTests.java +++ b/access/src/test/java/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptorTests.java @@ -30,10 +30,10 @@ import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.springframework.security.TargetObject; import org.springframework.security.access.AccessDecisionManager; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.SecurityConfig; +import org.springframework.security.access.TargetObject; import org.springframework.security.access.intercept.AfterInvocationManager; import org.springframework.security.access.intercept.RunAsManager; import org.springframework.security.access.intercept.RunAsUserToken; diff --git a/core/src/test/java/org/springframework/security/access/intercept/method/MapBasedMethodSecurityMetadataSourceTests.java b/access/src/test/java/org/springframework/security/access/intercept/method/MapBasedMethodSecurityMetadataSourceTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/intercept/method/MapBasedMethodSecurityMetadataSourceTests.java rename to access/src/test/java/org/springframework/security/access/intercept/method/MapBasedMethodSecurityMetadataSourceTests.java diff --git a/core/src/test/java/org/springframework/security/access/intercept/method/MethodInvocationPrivilegeEvaluatorTests.java b/access/src/test/java/org/springframework/security/access/intercept/method/MethodInvocationPrivilegeEvaluatorTests.java similarity index 96% rename from core/src/test/java/org/springframework/security/access/intercept/method/MethodInvocationPrivilegeEvaluatorTests.java rename to access/src/test/java/org/springframework/security/access/intercept/method/MethodInvocationPrivilegeEvaluatorTests.java index 93482a82cb..4780a8cc44 100644 --- a/core/src/test/java/org/springframework/security/access/intercept/method/MethodInvocationPrivilegeEvaluatorTests.java +++ b/access/src/test/java/org/springframework/security/access/intercept/method/MethodInvocationPrivilegeEvaluatorTests.java @@ -22,13 +22,13 @@ import org.aopalliance.intercept.MethodInvocation; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.security.ITargetObject; -import org.springframework.security.OtherTargetObject; -import org.springframework.security.TargetObject; import org.springframework.security.access.AccessDecisionManager; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.ConfigAttribute; +import org.springframework.security.access.ITargetObject; +import org.springframework.security.access.OtherTargetObject; import org.springframework.security.access.SecurityConfig; +import org.springframework.security.access.TargetObject; import org.springframework.security.access.intercept.MethodInvocationPrivilegeEvaluator; import org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor; import org.springframework.security.access.method.MethodSecurityMetadataSource; diff --git a/core/src/test/java/org/springframework/security/access/intercept/method/MockMethodInvocation.java b/access/src/test/java/org/springframework/security/access/intercept/method/MockMethodInvocation.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/intercept/method/MockMethodInvocation.java rename to access/src/test/java/org/springframework/security/access/intercept/method/MockMethodInvocation.java diff --git a/core/src/test/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSourceTests.java b/access/src/test/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSourceTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSourceTests.java rename to access/src/test/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSourceTests.java diff --git a/core/src/test/java/org/springframework/security/access/prepost/PostInvocationAdviceProviderTests.java b/access/src/test/java/org/springframework/security/access/prepost/PostInvocationAdviceProviderTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/prepost/PostInvocationAdviceProviderTests.java rename to access/src/test/java/org/springframework/security/access/prepost/PostInvocationAdviceProviderTests.java diff --git a/core/src/test/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoterTests.java b/access/src/test/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoterTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoterTests.java rename to access/src/test/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoterTests.java diff --git a/core/src/test/java/org/springframework/security/access/vote/AbstractAccessDecisionManagerTests.java b/access/src/test/java/org/springframework/security/access/vote/AbstractAccessDecisionManagerTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/vote/AbstractAccessDecisionManagerTests.java rename to access/src/test/java/org/springframework/security/access/vote/AbstractAccessDecisionManagerTests.java diff --git a/core/src/test/java/org/springframework/security/access/vote/AbstractAclVoterTests.java b/access/src/test/java/org/springframework/security/access/vote/AbstractAclVoterTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/vote/AbstractAclVoterTests.java rename to access/src/test/java/org/springframework/security/access/vote/AbstractAclVoterTests.java diff --git a/core/src/test/java/org/springframework/security/access/vote/AffirmativeBasedTests.java b/access/src/test/java/org/springframework/security/access/vote/AffirmativeBasedTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/vote/AffirmativeBasedTests.java rename to access/src/test/java/org/springframework/security/access/vote/AffirmativeBasedTests.java diff --git a/core/src/test/java/org/springframework/security/access/vote/AuthenticatedVoterTests.java b/access/src/test/java/org/springframework/security/access/vote/AuthenticatedVoterTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/vote/AuthenticatedVoterTests.java rename to access/src/test/java/org/springframework/security/access/vote/AuthenticatedVoterTests.java diff --git a/core/src/test/java/org/springframework/security/access/vote/ConsensusBasedTests.java b/access/src/test/java/org/springframework/security/access/vote/ConsensusBasedTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/vote/ConsensusBasedTests.java rename to access/src/test/java/org/springframework/security/access/vote/ConsensusBasedTests.java diff --git a/core/src/test/java/org/springframework/security/access/vote/DenyAgainVoter.java b/access/src/test/java/org/springframework/security/access/vote/DenyAgainVoter.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/vote/DenyAgainVoter.java rename to access/src/test/java/org/springframework/security/access/vote/DenyAgainVoter.java diff --git a/core/src/test/java/org/springframework/security/access/vote/DenyVoter.java b/access/src/test/java/org/springframework/security/access/vote/DenyVoter.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/vote/DenyVoter.java rename to access/src/test/java/org/springframework/security/access/vote/DenyVoter.java diff --git a/core/src/test/java/org/springframework/security/access/vote/RoleHierarchyVoterTests.java b/access/src/test/java/org/springframework/security/access/vote/RoleHierarchyVoterTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/vote/RoleHierarchyVoterTests.java rename to access/src/test/java/org/springframework/security/access/vote/RoleHierarchyVoterTests.java diff --git a/core/src/test/java/org/springframework/security/access/vote/RoleVoterTests.java b/access/src/test/java/org/springframework/security/access/vote/RoleVoterTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/vote/RoleVoterTests.java rename to access/src/test/java/org/springframework/security/access/vote/RoleVoterTests.java diff --git a/core/src/test/java/org/springframework/security/access/vote/UnanimousBasedTests.java b/access/src/test/java/org/springframework/security/access/vote/UnanimousBasedTests.java similarity index 100% rename from core/src/test/java/org/springframework/security/access/vote/UnanimousBasedTests.java rename to access/src/test/java/org/springframework/security/access/vote/UnanimousBasedTests.java diff --git a/acl/spring-security-acl.gradle b/acl/spring-security-acl.gradle index ec3d59bbe7..0238984aab 100644 --- a/acl/spring-security-acl.gradle +++ b/acl/spring-security-acl.gradle @@ -9,6 +9,8 @@ dependencies { api 'org.springframework:spring-jdbc' api 'org.springframework:spring-tx' + optional project(':spring-security-access') + testImplementation "org.assertj:assertj-core" testImplementation "org.junit.jupiter:junit-jupiter-api" testImplementation "org.junit.jupiter:junit-jupiter-params" diff --git a/aspects/spring-security-aspects.gradle b/aspects/spring-security-aspects.gradle index cffa8e5fb1..9df4e61538 100644 --- a/aspects/spring-security-aspects.gradle +++ b/aspects/spring-security-aspects.gradle @@ -18,6 +18,8 @@ dependencies { api 'org.springframework:spring-context' api 'org.springframework:spring-core' + optional project(':spring-security-access') + testImplementation 'org.springframework:spring-aop' testImplementation "org.assertj:assertj-core" testImplementation "org.junit.jupiter:junit-jupiter-api" diff --git a/config/spring-security-config.gradle b/config/spring-security-config.gradle index 502bc446fd..c912dc6cdc 100644 --- a/config/spring-security-config.gradle +++ b/config/spring-security-config.gradle @@ -1,4 +1,3 @@ -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.springframework.gradle.xsd.CreateVersionlessXsdTask import trang.RncToXsd @@ -21,6 +20,7 @@ dependencies { api 'org.springframework:spring-context' api 'org.springframework:spring-core' + optional project(':spring-security-access') optional project(':spring-security-data') optional project(':spring-security-ldap') optional project(':spring-security-messaging') @@ -49,6 +49,7 @@ dependencies { testImplementation project(':spring-security-aspects') testImplementation project(':spring-security-cas') testImplementation project(':spring-security-test') + testImplementation project(path : ':spring-security-access', configuration : 'tests') testImplementation project(path : ':spring-security-core', configuration : 'tests') testImplementation project(path : ':spring-security-ldap', configuration : 'tests') testImplementation project(path : ':spring-security-oauth2-client', configuration : 'tests') diff --git a/core/src/main/java/org/springframework/security/core/parameters/AnnotationParameterNameDiscoverer.java b/core/src/main/java/org/springframework/security/core/parameters/AnnotationParameterNameDiscoverer.java index fca66904bd..6426fcc01a 100644 --- a/core/src/main/java/org/springframework/security/core/parameters/AnnotationParameterNameDiscoverer.java +++ b/core/src/main/java/org/springframework/security/core/parameters/AnnotationParameterNameDiscoverer.java @@ -30,7 +30,6 @@ import org.springframework.core.BridgeMethodResolver; import org.springframework.core.ParameterNameDiscoverer; import org.springframework.core.PrioritizedParameterNameDiscoverer; import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.security.access.method.P; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; diff --git a/core/src/test/java/org/springframework/security/authorization/method/AuthorizationManagerAfterReactiveMethodInterceptorTests.java b/core/src/test/java/org/springframework/security/authorization/method/AuthorizationManagerAfterReactiveMethodInterceptorTests.java index bbc363ca18..3c2358964d 100644 --- a/core/src/test/java/org/springframework/security/authorization/method/AuthorizationManagerAfterReactiveMethodInterceptorTests.java +++ b/core/src/test/java/org/springframework/security/authorization/method/AuthorizationManagerAfterReactiveMethodInterceptorTests.java @@ -25,7 +25,6 @@ import reactor.core.publisher.Mono; import org.springframework.aop.Pointcut; import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.access.intercept.method.MockMethodInvocation; import org.springframework.security.authorization.AuthorizationDecision; import org.springframework.security.authorization.AuthorizationDeniedException; import org.springframework.security.authorization.AuthorizationResult; diff --git a/core/src/test/java/org/springframework/security/authorization/method/AuthorizationManagerBeforeReactiveMethodInterceptorTests.java b/core/src/test/java/org/springframework/security/authorization/method/AuthorizationManagerBeforeReactiveMethodInterceptorTests.java index fbdf5c09ed..09b069302a 100644 --- a/core/src/test/java/org/springframework/security/authorization/method/AuthorizationManagerBeforeReactiveMethodInterceptorTests.java +++ b/core/src/test/java/org/springframework/security/authorization/method/AuthorizationManagerBeforeReactiveMethodInterceptorTests.java @@ -24,7 +24,6 @@ import reactor.core.publisher.Mono; import org.springframework.aop.Pointcut; import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.access.intercept.method.MockMethodInvocation; import org.springframework.security.authorization.AuthorizationDecision; import org.springframework.security.authorization.AuthorizationDeniedException; import org.springframework.security.authorization.AuthorizationResult; diff --git a/core/src/test/java/org/springframework/security/authorization/method/BusinessService.java b/core/src/test/java/org/springframework/security/authorization/method/BusinessService.java new file mode 100644 index 0000000000..aa90b2c22c --- /dev/null +++ b/core/src/test/java/org/springframework/security/authorization/method/BusinessService.java @@ -0,0 +1,70 @@ +/* + * Copyright 2004, 2005, 2006 Acegi Technology Pty Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.authorization.method; + +import java.io.Serializable; +import java.util.List; + +import jakarta.annotation.security.PermitAll; +import jakarta.annotation.security.RolesAllowed; + +import org.springframework.security.access.annotation.Secured; +import org.springframework.security.access.prepost.PreAuthorize; + +/** + */ +@Secured({ "ROLE_USER" }) +@PermitAll +public interface BusinessService extends Serializable { + + @Secured({ "ROLE_ADMIN" }) + @RolesAllowed({ "ROLE_ADMIN" }) + @PreAuthorize("hasRole('ROLE_ADMIN')") + void someAdminMethod(); + + @Secured({ "ROLE_USER", "ROLE_ADMIN" }) + @RolesAllowed({ "ROLE_USER", "ROLE_ADMIN" }) + void someUserAndAdminMethod(); + + @Secured({ "ROLE_USER" }) + @RolesAllowed({ "ROLE_USER" }) + void someUserMethod1(); + + @Secured({ "ROLE_USER" }) + @RolesAllowed({ "ROLE_USER" }) + void someUserMethod2(); + + @RolesAllowed({ "USER" }) + void rolesAllowedUser(); + + int someOther(String s); + + int someOther(int input); + + List methodReturningAList(List someList); + + Object[] methodReturningAnArray(Object[] someArray); + + List methodReturningAList(String userName, String extraParam); + + @RequireAdminRole + @RequireUserRole + default void repeatedAnnotations() { + + } + +} diff --git a/core/src/test/java/org/springframework/security/authorization/method/Jsr250AuthorizationManagerTests.java b/core/src/test/java/org/springframework/security/authorization/method/Jsr250AuthorizationManagerTests.java index d5174a2232..d9534a7df0 100644 --- a/core/src/test/java/org/springframework/security/authorization/method/Jsr250AuthorizationManagerTests.java +++ b/core/src/test/java/org/springframework/security/authorization/method/Jsr250AuthorizationManagerTests.java @@ -28,7 +28,6 @@ import jakarta.annotation.security.RolesAllowed; import org.junit.jupiter.api.Test; import org.springframework.core.annotation.AnnotationConfigurationException; -import org.springframework.security.access.intercept.method.MockMethodInvocation; import org.springframework.security.authentication.TestAuthentication; import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.authorization.AuthorizationManager; diff --git a/core/src/test/java/org/springframework/security/authorization/method/MethodExpressionAuthorizationManagerTests.java b/core/src/test/java/org/springframework/security/authorization/method/MethodExpressionAuthorizationManagerTests.java index c3357a20f0..3aea48707e 100644 --- a/core/src/test/java/org/springframework/security/authorization/method/MethodExpressionAuthorizationManagerTests.java +++ b/core/src/test/java/org/springframework/security/authorization/method/MethodExpressionAuthorizationManagerTests.java @@ -21,7 +21,6 @@ import org.junit.platform.commons.util.ReflectionUtils; import org.springframework.expression.Expression; import org.springframework.expression.ExpressionParser; -import org.springframework.security.access.annotation.BusinessService; import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; import org.springframework.security.authentication.TestAuthentication; import org.springframework.security.authorization.AuthorizationResult; diff --git a/core/src/test/java/org/springframework/security/authorization/method/MockMethodInvocation.java b/core/src/test/java/org/springframework/security/authorization/method/MockMethodInvocation.java new file mode 100644 index 0000000000..ee5b35cfff --- /dev/null +++ b/core/src/test/java/org/springframework/security/authorization/method/MockMethodInvocation.java @@ -0,0 +1,75 @@ +/* + * Copyright 2004-present 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.authorization.method; + +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Method; + +import org.aopalliance.intercept.MethodInvocation; + +@SuppressWarnings("unchecked") +public class MockMethodInvocation implements MethodInvocation { + + private Method method; + + private Object targetObject; + + private Object[] arguments = new Object[0]; + + public MockMethodInvocation(Object targetObject, Class clazz, String methodName, Class[] parameterTypes, + Object[] arguments) throws NoSuchMethodException { + this(targetObject, clazz, methodName, parameterTypes); + this.arguments = arguments; + } + + public MockMethodInvocation(Object targetObject, Class clazz, String methodName, Class... parameterTypes) + throws NoSuchMethodException { + this(targetObject, clazz.getMethod(methodName, parameterTypes)); + this.targetObject = targetObject; + } + + public MockMethodInvocation(Object targetObject, Method method) { + this.targetObject = targetObject; + this.method = method; + } + + @Override + public Object[] getArguments() { + return this.arguments; + } + + @Override + public Method getMethod() { + return this.method; + } + + @Override + public AccessibleObject getStaticPart() { + return null; + } + + @Override + public Object getThis() { + return this.targetObject; + } + + @Override + public Object proceed() { + return null; + } + +} diff --git a/core/src/test/java/org/springframework/security/authorization/method/PostAuthorizeAuthorizationManagerTests.java b/core/src/test/java/org/springframework/security/authorization/method/PostAuthorizeAuthorizationManagerTests.java index dd1a4a8359..9e418096f9 100644 --- a/core/src/test/java/org/springframework/security/authorization/method/PostAuthorizeAuthorizationManagerTests.java +++ b/core/src/test/java/org/springframework/security/authorization/method/PostAuthorizeAuthorizationManagerTests.java @@ -30,7 +30,6 @@ import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.annotation.AnnotationConfigurationException; import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; -import org.springframework.security.access.intercept.method.MockMethodInvocation; import org.springframework.security.access.prepost.PostAuthorize; import org.springframework.security.authentication.TestAuthentication; import org.springframework.security.authentication.TestingAuthenticationToken; diff --git a/core/src/test/java/org/springframework/security/authorization/method/PostAuthorizeReactiveAuthorizationManagerTests.java b/core/src/test/java/org/springframework/security/authorization/method/PostAuthorizeReactiveAuthorizationManagerTests.java index f5e51d4efc..5c10366bd2 100644 --- a/core/src/test/java/org/springframework/security/authorization/method/PostAuthorizeReactiveAuthorizationManagerTests.java +++ b/core/src/test/java/org/springframework/security/authorization/method/PostAuthorizeReactiveAuthorizationManagerTests.java @@ -28,7 +28,6 @@ import reactor.core.publisher.Mono; import org.springframework.core.annotation.AnnotationConfigurationException; import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; -import org.springframework.security.access.intercept.method.MockMethodInvocation; import org.springframework.security.access.prepost.PostAuthorize; import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.authorization.AuthorizationResult; diff --git a/core/src/test/java/org/springframework/security/authorization/method/PostFilterAuthorizationMethodInterceptorTests.java b/core/src/test/java/org/springframework/security/authorization/method/PostFilterAuthorizationMethodInterceptorTests.java index b837b20cf6..31fee409f9 100644 --- a/core/src/test/java/org/springframework/security/authorization/method/PostFilterAuthorizationMethodInterceptorTests.java +++ b/core/src/test/java/org/springframework/security/authorization/method/PostFilterAuthorizationMethodInterceptorTests.java @@ -28,7 +28,6 @@ import org.springframework.aop.MethodMatcher; import org.springframework.core.annotation.AnnotationConfigurationException; import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; -import org.springframework.security.access.intercept.method.MockMethodInvocation; import org.springframework.security.access.prepost.PostFilter; import org.springframework.security.authentication.TestAuthentication; import org.springframework.security.authentication.TestingAuthenticationToken; diff --git a/core/src/test/java/org/springframework/security/authorization/method/PostFilterAuthorizationReactiveMethodInterceptorTests.java b/core/src/test/java/org/springframework/security/authorization/method/PostFilterAuthorizationReactiveMethodInterceptorTests.java index f4b1dbcf19..aed760b585 100644 --- a/core/src/test/java/org/springframework/security/authorization/method/PostFilterAuthorizationReactiveMethodInterceptorTests.java +++ b/core/src/test/java/org/springframework/security/authorization/method/PostFilterAuthorizationReactiveMethodInterceptorTests.java @@ -27,7 +27,6 @@ import reactor.core.publisher.Mono; import org.springframework.core.annotation.AnnotationConfigurationException; import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; -import org.springframework.security.access.intercept.method.MockMethodInvocation; import org.springframework.security.access.prepost.PostFilter; import static org.assertj.core.api.Assertions.assertThat; diff --git a/core/src/test/java/org/springframework/security/authorization/method/PreAuthorizeAuthorizationManagerTests.java b/core/src/test/java/org/springframework/security/authorization/method/PreAuthorizeAuthorizationManagerTests.java index 980f640750..b9439ca3d6 100644 --- a/core/src/test/java/org/springframework/security/authorization/method/PreAuthorizeAuthorizationManagerTests.java +++ b/core/src/test/java/org/springframework/security/authorization/method/PreAuthorizeAuthorizationManagerTests.java @@ -28,7 +28,6 @@ import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.annotation.AnnotationConfigurationException; import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; -import org.springframework.security.access.intercept.method.MockMethodInvocation; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.authentication.TestAuthentication; import org.springframework.security.authentication.TestingAuthenticationToken; diff --git a/core/src/test/java/org/springframework/security/authorization/method/PreAuthorizeReactiveAuthorizationManagerTests.java b/core/src/test/java/org/springframework/security/authorization/method/PreAuthorizeReactiveAuthorizationManagerTests.java index f62fe7459c..bb0d003e3d 100644 --- a/core/src/test/java/org/springframework/security/authorization/method/PreAuthorizeReactiveAuthorizationManagerTests.java +++ b/core/src/test/java/org/springframework/security/authorization/method/PreAuthorizeReactiveAuthorizationManagerTests.java @@ -25,7 +25,6 @@ import reactor.core.publisher.Mono; import org.springframework.core.annotation.AnnotationConfigurationException; import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; -import org.springframework.security.access.intercept.method.MockMethodInvocation; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.authorization.AuthorizationResult; diff --git a/core/src/test/java/org/springframework/security/authorization/method/PreFilterAuthorizationMethodInterceptorTests.java b/core/src/test/java/org/springframework/security/authorization/method/PreFilterAuthorizationMethodInterceptorTests.java index d13bce3c4d..e28c570644 100644 --- a/core/src/test/java/org/springframework/security/authorization/method/PreFilterAuthorizationMethodInterceptorTests.java +++ b/core/src/test/java/org/springframework/security/authorization/method/PreFilterAuthorizationMethodInterceptorTests.java @@ -29,7 +29,6 @@ import org.springframework.aop.MethodMatcher; import org.springframework.core.annotation.AnnotationConfigurationException; import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; -import org.springframework.security.access.intercept.method.MockMethodInvocation; import org.springframework.security.access.prepost.PreFilter; import org.springframework.security.authentication.TestAuthentication; import org.springframework.security.authentication.TestingAuthenticationToken; diff --git a/core/src/test/java/org/springframework/security/authorization/method/PreFilterAuthorizationReactiveMethodInterceptorTests.java b/core/src/test/java/org/springframework/security/authorization/method/PreFilterAuthorizationReactiveMethodInterceptorTests.java index e45c6054ae..309321e607 100644 --- a/core/src/test/java/org/springframework/security/authorization/method/PreFilterAuthorizationReactiveMethodInterceptorTests.java +++ b/core/src/test/java/org/springframework/security/authorization/method/PreFilterAuthorizationReactiveMethodInterceptorTests.java @@ -28,7 +28,6 @@ import org.springframework.core.ParameterNameDiscoverer; import org.springframework.core.annotation.AnnotationConfigurationException; import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; -import org.springframework.security.access.intercept.method.MockMethodInvocation; import org.springframework.security.access.prepost.PreFilter; import org.springframework.security.core.parameters.DefaultSecurityParameterNameDiscoverer; diff --git a/core/src/test/java/org/springframework/security/authorization/method/RequireAdminRole.java b/core/src/test/java/org/springframework/security/authorization/method/RequireAdminRole.java new file mode 100644 index 0000000000..c9d2101d5a --- /dev/null +++ b/core/src/test/java/org/springframework/security/authorization/method/RequireAdminRole.java @@ -0,0 +1,33 @@ +/* + * Copyright 2004-present 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.authorization.method; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import jakarta.annotation.security.RolesAllowed; + +import org.springframework.security.access.annotation.Secured; +import org.springframework.security.access.prepost.PreAuthorize; + +@Retention(RetentionPolicy.RUNTIME) +@PreAuthorize("hasRole('ADMIN')") +@RolesAllowed("ADMIN") +@Secured("ADMIN") +public @interface RequireAdminRole { + +} diff --git a/core/src/test/java/org/springframework/security/authorization/method/RequireUserRole.java b/core/src/test/java/org/springframework/security/authorization/method/RequireUserRole.java new file mode 100644 index 0000000000..b918926b3e --- /dev/null +++ b/core/src/test/java/org/springframework/security/authorization/method/RequireUserRole.java @@ -0,0 +1,33 @@ +/* + * Copyright 2004-present 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.authorization.method; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import jakarta.annotation.security.RolesAllowed; + +import org.springframework.security.access.annotation.Secured; +import org.springframework.security.access.prepost.PreAuthorize; + +@Retention(RetentionPolicy.RUNTIME) +@PreAuthorize("hasRole('USER')") +@RolesAllowed("USER") +@Secured("USER") +public @interface RequireUserRole { + +} diff --git a/core/src/test/java/org/springframework/security/authorization/method/SecuredAuthorizationManagerTests.java b/core/src/test/java/org/springframework/security/authorization/method/SecuredAuthorizationManagerTests.java index 172d9be8b6..27993c2fd0 100644 --- a/core/src/test/java/org/springframework/security/authorization/method/SecuredAuthorizationManagerTests.java +++ b/core/src/test/java/org/springframework/security/authorization/method/SecuredAuthorizationManagerTests.java @@ -27,7 +27,6 @@ import org.junit.jupiter.api.Test; import org.springframework.aop.TargetClassAware; import org.springframework.core.annotation.AnnotationConfigurationException; import org.springframework.security.access.annotation.Secured; -import org.springframework.security.access.intercept.method.MockMethodInvocation; import org.springframework.security.authentication.TestAuthentication; import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.authorization.AuthorizationManager; diff --git a/core/src/test/java/org/springframework/security/core/parameters/AnnotationParameterNameDiscovererTests.java b/core/src/test/java/org/springframework/security/core/parameters/AnnotationParameterNameDiscovererTests.java index 13dee89fe5..de52d16246 100644 --- a/core/src/test/java/org/springframework/security/core/parameters/AnnotationParameterNameDiscovererTests.java +++ b/core/src/test/java/org/springframework/security/core/parameters/AnnotationParameterNameDiscovererTests.java @@ -19,7 +19,6 @@ package org.springframework.security.core.parameters; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.security.access.method.P; import org.springframework.util.ReflectionUtils; import static org.assertj.core.api.Assertions.assertThat; diff --git a/core/src/test/java/org/springframework/security/util/BusinessService.java b/core/src/test/java/org/springframework/security/util/BusinessService.java new file mode 100644 index 0000000000..d863bb55e8 --- /dev/null +++ b/core/src/test/java/org/springframework/security/util/BusinessService.java @@ -0,0 +1,70 @@ +/* + * Copyright 2004, 2005, 2006 Acegi Technology Pty Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.util; + +import java.io.Serializable; +import java.util.List; + +import jakarta.annotation.security.PermitAll; +import jakarta.annotation.security.RolesAllowed; + +import org.springframework.security.access.annotation.Secured; +import org.springframework.security.access.prepost.PreAuthorize; + +/** + */ +@Secured({ "ROLE_USER" }) +@PermitAll +public interface BusinessService extends Serializable { + + @Secured({ "ROLE_ADMIN" }) + @RolesAllowed({ "ROLE_ADMIN" }) + @PreAuthorize("hasRole('ROLE_ADMIN')") + void someAdminMethod(); + + @Secured({ "ROLE_USER", "ROLE_ADMIN" }) + @RolesAllowed({ "ROLE_USER", "ROLE_ADMIN" }) + void someUserAndAdminMethod(); + + @Secured({ "ROLE_USER" }) + @RolesAllowed({ "ROLE_USER" }) + void someUserMethod1(); + + @Secured({ "ROLE_USER" }) + @RolesAllowed({ "ROLE_USER" }) + void someUserMethod2(); + + @RolesAllowed({ "USER" }) + void rolesAllowedUser(); + + int someOther(String s); + + int someOther(int input); + + List methodReturningAList(List someList); + + Object[] methodReturningAnArray(Object[] someArray); + + List methodReturningAList(String userName, String extraParam); + + @RequireAdminRole + @RequireUserRole + default void repeatedAnnotations() { + + } + +} diff --git a/core/src/test/java/org/springframework/security/util/BusinessServiceImpl.java b/core/src/test/java/org/springframework/security/util/BusinessServiceImpl.java new file mode 100644 index 0000000000..60b1997d37 --- /dev/null +++ b/core/src/test/java/org/springframework/security/util/BusinessServiceImpl.java @@ -0,0 +1,84 @@ +/* + * Copyright 2004-present 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.util; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.security.access.annotation.Secured; +import org.springframework.security.authorization.method.BusinessService; + +/** + * @author Joe Scalise + */ +@SuppressWarnings("serial") +public class BusinessServiceImpl implements BusinessService { + + @Override + @Secured({ "ROLE_USER" }) + public void someUserMethod1() { + } + + @Override + @Secured({ "ROLE_USER" }) + public void someUserMethod2() { + } + + @Override + @Secured({ "ROLE_USER", "ROLE_ADMIN" }) + public void someUserAndAdminMethod() { + } + + @Override + @Secured({ "ROLE_ADMIN" }) + public void someAdminMethod() { + } + + public E someUserMethod3(final E entity) { + return entity; + } + + @Override + public int someOther(String s) { + return 0; + } + + @Override + public int someOther(int input) { + return input; + } + + @Override + public List methodReturningAList(List someList) { + return someList; + } + + @Override + public List methodReturningAList(String userName, String arg2) { + return new ArrayList<>(); + } + + @Override + public Object[] methodReturningAnArray(Object[] someArray) { + return null; + } + + @Override + public void rolesAllowedUser() { + } + +} diff --git a/core/src/test/java/org/springframework/security/util/Entity.java b/core/src/test/java/org/springframework/security/util/Entity.java new file mode 100644 index 0000000000..e4bbb1e3d3 --- /dev/null +++ b/core/src/test/java/org/springframework/security/util/Entity.java @@ -0,0 +1,30 @@ +/* + * Copyright 2004-present 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.util; + +/** + * Class to act as a superclass for annotations testing. + * + * @author Ben Alex + * + */ +public class Entity { + + public Entity(String someParameter) { + } + +} diff --git a/core/src/test/java/org/springframework/security/util/MethodInvocationUtilsTests.java b/core/src/test/java/org/springframework/security/util/MethodInvocationUtilsTests.java index 255695fe1d..1a04a6d685 100644 --- a/core/src/test/java/org/springframework/security/util/MethodInvocationUtilsTests.java +++ b/core/src/test/java/org/springframework/security/util/MethodInvocationUtilsTests.java @@ -22,7 +22,6 @@ import org.aopalliance.intercept.MethodInvocation; import org.junit.jupiter.api.Test; import org.springframework.aop.framework.AdvisedSupport; -import org.springframework.security.access.annotation.BusinessServiceImpl; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; diff --git a/core/src/test/java/org/springframework/security/util/RequireAdminRole.java b/core/src/test/java/org/springframework/security/util/RequireAdminRole.java new file mode 100644 index 0000000000..fb6e5d45ac --- /dev/null +++ b/core/src/test/java/org/springframework/security/util/RequireAdminRole.java @@ -0,0 +1,33 @@ +/* + * Copyright 2004-present 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.util; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import jakarta.annotation.security.RolesAllowed; + +import org.springframework.security.access.annotation.Secured; +import org.springframework.security.access.prepost.PreAuthorize; + +@Retention(RetentionPolicy.RUNTIME) +@PreAuthorize("hasRole('ADMIN')") +@RolesAllowed("ADMIN") +@Secured("ADMIN") +public @interface RequireAdminRole { + +} diff --git a/core/src/test/java/org/springframework/security/util/RequireUserRole.java b/core/src/test/java/org/springframework/security/util/RequireUserRole.java new file mode 100644 index 0000000000..6ea9c9e25f --- /dev/null +++ b/core/src/test/java/org/springframework/security/util/RequireUserRole.java @@ -0,0 +1,33 @@ +/* + * Copyright 2004-present 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.util; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import jakarta.annotation.security.RolesAllowed; + +import org.springframework.security.access.annotation.Secured; +import org.springframework.security.access.prepost.PreAuthorize; + +@Retention(RetentionPolicy.RUNTIME) +@PreAuthorize("hasRole('USER')") +@RolesAllowed("USER") +@Secured("USER") +public @interface RequireUserRole { + +} diff --git a/itest/context/spring-security-itest-context.gradle b/itest/context/spring-security-itest-context.gradle index 15c4b52dbd..23064eaf72 100644 --- a/itest/context/spring-security-itest-context.gradle +++ b/itest/context/spring-security-itest-context.gradle @@ -3,6 +3,7 @@ apply plugin: 'io.spring.convention.spring-test' dependencies { implementation platform(project(":spring-security-dependencies")) implementation project(':spring-security-core') + implementation project(':spring-security-access') implementation 'org.python:jython' implementation 'org.springframework:spring-aop' implementation 'org.springframework:spring-beans' diff --git a/itest/web/spring-security-itest-web.gradle b/itest/web/spring-security-itest-web.gradle index d8fe2583a2..e7cf83a4f5 100644 --- a/itest/web/spring-security-itest-web.gradle +++ b/itest/web/spring-security-itest-web.gradle @@ -2,6 +2,7 @@ apply plugin: 'io.spring.convention.spring-test' dependencies { implementation platform(project(":spring-security-dependencies")) + implementation project(':spring-security-access') implementation 'org.springframework:spring-context' implementation 'org.springframework:spring-web' diff --git a/messaging/spring-security-messaging.gradle b/messaging/spring-security-messaging.gradle index c231057267..044afa0ba0 100644 --- a/messaging/spring-security-messaging.gradle +++ b/messaging/spring-security-messaging.gradle @@ -13,6 +13,7 @@ dependencies { api 'org.springframework:spring-expression' api 'org.springframework:spring-messaging' + optional project(':spring-security-access') optional project(':spring-security-web') optional 'org.springframework:spring-websocket' optional 'io.projectreactor:reactor-core' diff --git a/web/spring-security-web.gradle b/web/spring-security-web.gradle index 87ce691e0c..d4113fed83 100644 --- a/web/spring-security-web.gradle +++ b/web/spring-security-web.gradle @@ -39,6 +39,7 @@ dependencies { api 'org.springframework:spring-expression' api 'org.springframework:spring-web' + optional project(':spring-security-access') optional 'com.fasterxml.jackson.core:jackson-databind' optional 'io.micrometer:context-propagation' optional 'io.projectreactor:reactor-core' From 3182883e2e8ec0742d097d47f144dc38cb7ee51d Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Tue, 2 Sep 2025 15:50:57 -0600 Subject: [PATCH 3/6] Move Messaging Access API Issue gh-17847 --- access/spring-security-access.gradle | 2 ++ .../access/expression/EvaluationContextPostProcessor.java | 0 .../ExpressionBasedMessageSecurityMetadataSourceFactory.java | 0 .../access/expression/MessageExpressionConfigAttribute.java | 0 .../messaging/access/expression/MessageExpressionVoter.java | 0 .../messaging/access/intercept/ChannelSecurityInterceptor.java | 2 +- .../access/intercept/DefaultMessageSecurityMetadataSource.java | 0 .../access/intercept/MessageSecurityMetadataSource.java | 0 ...xpressionBasedMessageSecurityMetadataSourceFactoryTests.java | 0 .../expression/MessageExpressionConfigAttributeTests.java | 0 .../access/expression/MessageExpressionVoterTests.java | 0 .../access/intercept/ChannelSecurityInterceptorTests.java | 0 .../intercept/DefaultMessageSecurityMetadataSourceTests.java | 0 messaging/spring-security-messaging.gradle | 1 - 14 files changed, 3 insertions(+), 2 deletions(-) rename {messaging => access}/src/main/java/org/springframework/security/messaging/access/expression/EvaluationContextPostProcessor.java (100%) rename {messaging => access}/src/main/java/org/springframework/security/messaging/access/expression/ExpressionBasedMessageSecurityMetadataSourceFactory.java (100%) rename {messaging => access}/src/main/java/org/springframework/security/messaging/access/expression/MessageExpressionConfigAttribute.java (100%) rename {messaging => access}/src/main/java/org/springframework/security/messaging/access/expression/MessageExpressionVoter.java (100%) rename {messaging => access}/src/main/java/org/springframework/security/messaging/access/intercept/ChannelSecurityInterceptor.java (98%) rename {messaging => access}/src/main/java/org/springframework/security/messaging/access/intercept/DefaultMessageSecurityMetadataSource.java (100%) rename {messaging => access}/src/main/java/org/springframework/security/messaging/access/intercept/MessageSecurityMetadataSource.java (100%) rename {messaging => access}/src/test/java/org/springframework/security/messaging/access/expression/ExpressionBasedMessageSecurityMetadataSourceFactoryTests.java (100%) rename {messaging => access}/src/test/java/org/springframework/security/messaging/access/expression/MessageExpressionConfigAttributeTests.java (100%) rename {messaging => access}/src/test/java/org/springframework/security/messaging/access/expression/MessageExpressionVoterTests.java (100%) rename {messaging => access}/src/test/java/org/springframework/security/messaging/access/intercept/ChannelSecurityInterceptorTests.java (100%) rename {messaging => access}/src/test/java/org/springframework/security/messaging/access/intercept/DefaultMessageSecurityMetadataSourceTests.java (100%) diff --git a/access/spring-security-access.gradle b/access/spring-security-access.gradle index ff53b8d766..355bac90b2 100644 --- a/access/spring-security-access.gradle +++ b/access/spring-security-access.gradle @@ -11,6 +11,8 @@ dependencies { api 'org.springframework:spring-expression' api 'io.micrometer:micrometer-observation' + optional project(':spring-security-messaging') + optional 'org.springframework:spring-websocket' optional 'com.fasterxml.jackson.core:jackson-databind' optional 'io.micrometer:context-propagation' optional 'io.projectreactor:reactor-core' diff --git a/messaging/src/main/java/org/springframework/security/messaging/access/expression/EvaluationContextPostProcessor.java b/access/src/main/java/org/springframework/security/messaging/access/expression/EvaluationContextPostProcessor.java similarity index 100% rename from messaging/src/main/java/org/springframework/security/messaging/access/expression/EvaluationContextPostProcessor.java rename to access/src/main/java/org/springframework/security/messaging/access/expression/EvaluationContextPostProcessor.java diff --git a/messaging/src/main/java/org/springframework/security/messaging/access/expression/ExpressionBasedMessageSecurityMetadataSourceFactory.java b/access/src/main/java/org/springframework/security/messaging/access/expression/ExpressionBasedMessageSecurityMetadataSourceFactory.java similarity index 100% rename from messaging/src/main/java/org/springframework/security/messaging/access/expression/ExpressionBasedMessageSecurityMetadataSourceFactory.java rename to access/src/main/java/org/springframework/security/messaging/access/expression/ExpressionBasedMessageSecurityMetadataSourceFactory.java diff --git a/messaging/src/main/java/org/springframework/security/messaging/access/expression/MessageExpressionConfigAttribute.java b/access/src/main/java/org/springframework/security/messaging/access/expression/MessageExpressionConfigAttribute.java similarity index 100% rename from messaging/src/main/java/org/springframework/security/messaging/access/expression/MessageExpressionConfigAttribute.java rename to access/src/main/java/org/springframework/security/messaging/access/expression/MessageExpressionConfigAttribute.java diff --git a/messaging/src/main/java/org/springframework/security/messaging/access/expression/MessageExpressionVoter.java b/access/src/main/java/org/springframework/security/messaging/access/expression/MessageExpressionVoter.java similarity index 100% rename from messaging/src/main/java/org/springframework/security/messaging/access/expression/MessageExpressionVoter.java rename to access/src/main/java/org/springframework/security/messaging/access/expression/MessageExpressionVoter.java diff --git a/messaging/src/main/java/org/springframework/security/messaging/access/intercept/ChannelSecurityInterceptor.java b/access/src/main/java/org/springframework/security/messaging/access/intercept/ChannelSecurityInterceptor.java similarity index 98% rename from messaging/src/main/java/org/springframework/security/messaging/access/intercept/ChannelSecurityInterceptor.java rename to access/src/main/java/org/springframework/security/messaging/access/intercept/ChannelSecurityInterceptor.java index d4863b6919..9e6fc2aae6 100644 --- a/messaging/src/main/java/org/springframework/security/messaging/access/intercept/ChannelSecurityInterceptor.java +++ b/access/src/main/java/org/springframework/security/messaging/access/intercept/ChannelSecurityInterceptor.java @@ -38,7 +38,7 @@ import org.springframework.util.Assert; * * @author Rob Winch * @since 4.0 - * @deprecated Use {@link AuthorizationChannelInterceptor} instead + * @deprecated Use {@code AuthorizationChannelInterceptor} instead */ @Deprecated public final class ChannelSecurityInterceptor extends AbstractSecurityInterceptor implements ChannelInterceptor { diff --git a/messaging/src/main/java/org/springframework/security/messaging/access/intercept/DefaultMessageSecurityMetadataSource.java b/access/src/main/java/org/springframework/security/messaging/access/intercept/DefaultMessageSecurityMetadataSource.java similarity index 100% rename from messaging/src/main/java/org/springframework/security/messaging/access/intercept/DefaultMessageSecurityMetadataSource.java rename to access/src/main/java/org/springframework/security/messaging/access/intercept/DefaultMessageSecurityMetadataSource.java diff --git a/messaging/src/main/java/org/springframework/security/messaging/access/intercept/MessageSecurityMetadataSource.java b/access/src/main/java/org/springframework/security/messaging/access/intercept/MessageSecurityMetadataSource.java similarity index 100% rename from messaging/src/main/java/org/springframework/security/messaging/access/intercept/MessageSecurityMetadataSource.java rename to access/src/main/java/org/springframework/security/messaging/access/intercept/MessageSecurityMetadataSource.java diff --git a/messaging/src/test/java/org/springframework/security/messaging/access/expression/ExpressionBasedMessageSecurityMetadataSourceFactoryTests.java b/access/src/test/java/org/springframework/security/messaging/access/expression/ExpressionBasedMessageSecurityMetadataSourceFactoryTests.java similarity index 100% rename from messaging/src/test/java/org/springframework/security/messaging/access/expression/ExpressionBasedMessageSecurityMetadataSourceFactoryTests.java rename to access/src/test/java/org/springframework/security/messaging/access/expression/ExpressionBasedMessageSecurityMetadataSourceFactoryTests.java diff --git a/messaging/src/test/java/org/springframework/security/messaging/access/expression/MessageExpressionConfigAttributeTests.java b/access/src/test/java/org/springframework/security/messaging/access/expression/MessageExpressionConfigAttributeTests.java similarity index 100% rename from messaging/src/test/java/org/springframework/security/messaging/access/expression/MessageExpressionConfigAttributeTests.java rename to access/src/test/java/org/springframework/security/messaging/access/expression/MessageExpressionConfigAttributeTests.java diff --git a/messaging/src/test/java/org/springframework/security/messaging/access/expression/MessageExpressionVoterTests.java b/access/src/test/java/org/springframework/security/messaging/access/expression/MessageExpressionVoterTests.java similarity index 100% rename from messaging/src/test/java/org/springframework/security/messaging/access/expression/MessageExpressionVoterTests.java rename to access/src/test/java/org/springframework/security/messaging/access/expression/MessageExpressionVoterTests.java diff --git a/messaging/src/test/java/org/springframework/security/messaging/access/intercept/ChannelSecurityInterceptorTests.java b/access/src/test/java/org/springframework/security/messaging/access/intercept/ChannelSecurityInterceptorTests.java similarity index 100% rename from messaging/src/test/java/org/springframework/security/messaging/access/intercept/ChannelSecurityInterceptorTests.java rename to access/src/test/java/org/springframework/security/messaging/access/intercept/ChannelSecurityInterceptorTests.java diff --git a/messaging/src/test/java/org/springframework/security/messaging/access/intercept/DefaultMessageSecurityMetadataSourceTests.java b/access/src/test/java/org/springframework/security/messaging/access/intercept/DefaultMessageSecurityMetadataSourceTests.java similarity index 100% rename from messaging/src/test/java/org/springframework/security/messaging/access/intercept/DefaultMessageSecurityMetadataSourceTests.java rename to access/src/test/java/org/springframework/security/messaging/access/intercept/DefaultMessageSecurityMetadataSourceTests.java diff --git a/messaging/spring-security-messaging.gradle b/messaging/spring-security-messaging.gradle index 044afa0ba0..c231057267 100644 --- a/messaging/spring-security-messaging.gradle +++ b/messaging/spring-security-messaging.gradle @@ -13,7 +13,6 @@ dependencies { api 'org.springframework:spring-expression' api 'org.springframework:spring-messaging' - optional project(':spring-security-access') optional project(':spring-security-web') optional 'org.springframework:spring-websocket' optional 'io.projectreactor:reactor-core' From fa4806dbcc6455b0bd76c2af24b5024f9cfc7ef4 Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Tue, 2 Sep 2025 16:06:03 -0600 Subject: [PATCH 4/6] Move Web Access API Issue gh-17847 --- access/spring-security-access.gradle | 4 ++ ...efaultWebInvocationPrivilegeEvaluator.java | 0 .../channel/AbstractRetryEntryPoint.java | 0 .../channel/ChannelDecisionManager.java | 0 .../channel/ChannelDecisionManagerImpl.java | 0 .../web/access/channel/ChannelEntryPoint.java | 0 .../channel/ChannelProcessingFilter.java | 0 .../web/access/channel/ChannelProcessor.java | 0 .../channel/InsecureChannelProcessor.java | 0 .../channel/RetryWithHttpEntryPoint.java | 0 .../channel/RetryWithHttpsEntryPoint.java | 0 .../channel/SecureChannelProcessor.java | 0 .../web/access/channel/package-info.java | 0 .../DefaultWebSecurityExpressionHandler.java | 0 ...ilterInvocationSecurityMetadataSource.java | 0 .../WebExpressionConfigAttribute.java | 0 .../access/expression/WebExpressionVoter.java | 0 ...ilterInvocationSecurityMetadataSource.java | 0 ...ilterInvocationSecurityMetadataSource.java | 0 .../intercept/FilterSecurityInterceptor.java | 0 ...tWebInvocationPrivilegeEvaluatorTests.java | 48 +++++++++---------- .../ChannelDecisionManagerImplTests.java | 7 +-- .../channel/ChannelProcessingFilterTests.java | 8 ++-- .../InsecureChannelProcessorTests.java | 13 +++-- .../channel/RetryWithHttpEntryPointTests.java | 0 .../RetryWithHttpsEntryPointTests.java | 0 .../channel/SecureChannelProcessorTests.java | 13 +++-- ...aultWebSecurityExpressionHandlerTests.java | 0 ...InvocationSecurityMetadataSourceTests.java | 0 .../expression/WebExpressionVoterTests.java | 0 ...InvocationSecurityMetadataSourceTests.java | 14 +++--- .../FilterSecurityInterceptorTests.java | 4 +- taglibs/spring-security-taglibs.gradle | 1 + web/spring-security-web.gradle | 1 - ...ultHttpSecurityExpressionHandlerTests.java | 8 ++-- 35 files changed, 67 insertions(+), 54 deletions(-) rename {web => access}/src/main/java/org/springframework/security/web/access/DefaultWebInvocationPrivilegeEvaluator.java (100%) rename {web => access}/src/main/java/org/springframework/security/web/access/channel/AbstractRetryEntryPoint.java (100%) rename {web => access}/src/main/java/org/springframework/security/web/access/channel/ChannelDecisionManager.java (100%) rename {web => access}/src/main/java/org/springframework/security/web/access/channel/ChannelDecisionManagerImpl.java (100%) rename {web => access}/src/main/java/org/springframework/security/web/access/channel/ChannelEntryPoint.java (100%) rename {web => access}/src/main/java/org/springframework/security/web/access/channel/ChannelProcessingFilter.java (100%) rename {web => access}/src/main/java/org/springframework/security/web/access/channel/ChannelProcessor.java (100%) rename {web => access}/src/main/java/org/springframework/security/web/access/channel/InsecureChannelProcessor.java (100%) rename {web => access}/src/main/java/org/springframework/security/web/access/channel/RetryWithHttpEntryPoint.java (100%) rename {web => access}/src/main/java/org/springframework/security/web/access/channel/RetryWithHttpsEntryPoint.java (100%) rename {web => access}/src/main/java/org/springframework/security/web/access/channel/SecureChannelProcessor.java (100%) rename {web => access}/src/main/java/org/springframework/security/web/access/channel/package-info.java (100%) rename {web => access}/src/main/java/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandler.java (100%) rename {web => access}/src/main/java/org/springframework/security/web/access/expression/ExpressionBasedFilterInvocationSecurityMetadataSource.java (100%) rename {web => access}/src/main/java/org/springframework/security/web/access/expression/WebExpressionConfigAttribute.java (100%) rename {web => access}/src/main/java/org/springframework/security/web/access/expression/WebExpressionVoter.java (100%) rename {web => access}/src/main/java/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSource.java (100%) rename {web => access}/src/main/java/org/springframework/security/web/access/intercept/FilterInvocationSecurityMetadataSource.java (100%) rename {web => access}/src/main/java/org/springframework/security/web/access/intercept/FilterSecurityInterceptor.java (100%) rename {web => access}/src/test/java/org/springframework/security/web/access/DefaultWebInvocationPrivilegeEvaluatorTests.java (72%) rename {web => access}/src/test/java/org/springframework/security/web/access/channel/ChannelDecisionManagerImplTests.java (96%) rename {web => access}/src/test/java/org/springframework/security/web/access/channel/ChannelProcessingFilterTests.java (95%) rename {web => access}/src/test/java/org/springframework/security/web/access/channel/InsecureChannelProcessorTests.java (88%) rename {web => access}/src/test/java/org/springframework/security/web/access/channel/RetryWithHttpEntryPointTests.java (100%) rename {web => access}/src/test/java/org/springframework/security/web/access/channel/RetryWithHttpsEntryPointTests.java (100%) rename {web => access}/src/test/java/org/springframework/security/web/access/channel/SecureChannelProcessorTests.java (88%) rename {web => access}/src/test/java/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandlerTests.java (100%) rename {web => access}/src/test/java/org/springframework/security/web/access/expression/ExpressionBasedFilterInvocationSecurityMetadataSourceTests.java (100%) rename {web => access}/src/test/java/org/springframework/security/web/access/expression/WebExpressionVoterTests.java (100%) rename {web => access}/src/test/java/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSourceTests.java (90%) rename {web => access}/src/test/java/org/springframework/security/web/access/intercept/FilterSecurityInterceptorTests.java (97%) diff --git a/access/spring-security-access.gradle b/access/spring-security-access.gradle index 355bac90b2..cf176ec074 100644 --- a/access/spring-security-access.gradle +++ b/access/spring-security-access.gradle @@ -12,6 +12,7 @@ dependencies { api 'io.micrometer:micrometer-observation' optional project(':spring-security-messaging') + optional project(':spring-security-web') optional 'org.springframework:spring-websocket' optional 'com.fasterxml.jackson.core:jackson-databind' optional 'io.micrometer:context-propagation' @@ -22,6 +23,9 @@ dependencies { optional 'org.springframework:spring-tx' optional 'org.jetbrains.kotlinx:kotlinx-coroutines-reactor' + provided 'jakarta.servlet:jakarta.servlet-api' + + testImplementation project(path : ':spring-security-web', configuration : 'tests') testImplementation 'commons-collections:commons-collections' testImplementation 'io.projectreactor:reactor-test' testImplementation "org.assertj:assertj-core" diff --git a/web/src/main/java/org/springframework/security/web/access/DefaultWebInvocationPrivilegeEvaluator.java b/access/src/main/java/org/springframework/security/web/access/DefaultWebInvocationPrivilegeEvaluator.java similarity index 100% rename from web/src/main/java/org/springframework/security/web/access/DefaultWebInvocationPrivilegeEvaluator.java rename to access/src/main/java/org/springframework/security/web/access/DefaultWebInvocationPrivilegeEvaluator.java diff --git a/web/src/main/java/org/springframework/security/web/access/channel/AbstractRetryEntryPoint.java b/access/src/main/java/org/springframework/security/web/access/channel/AbstractRetryEntryPoint.java similarity index 100% rename from web/src/main/java/org/springframework/security/web/access/channel/AbstractRetryEntryPoint.java rename to access/src/main/java/org/springframework/security/web/access/channel/AbstractRetryEntryPoint.java diff --git a/web/src/main/java/org/springframework/security/web/access/channel/ChannelDecisionManager.java b/access/src/main/java/org/springframework/security/web/access/channel/ChannelDecisionManager.java similarity index 100% rename from web/src/main/java/org/springframework/security/web/access/channel/ChannelDecisionManager.java rename to access/src/main/java/org/springframework/security/web/access/channel/ChannelDecisionManager.java diff --git a/web/src/main/java/org/springframework/security/web/access/channel/ChannelDecisionManagerImpl.java b/access/src/main/java/org/springframework/security/web/access/channel/ChannelDecisionManagerImpl.java similarity index 100% rename from web/src/main/java/org/springframework/security/web/access/channel/ChannelDecisionManagerImpl.java rename to access/src/main/java/org/springframework/security/web/access/channel/ChannelDecisionManagerImpl.java diff --git a/web/src/main/java/org/springframework/security/web/access/channel/ChannelEntryPoint.java b/access/src/main/java/org/springframework/security/web/access/channel/ChannelEntryPoint.java similarity index 100% rename from web/src/main/java/org/springframework/security/web/access/channel/ChannelEntryPoint.java rename to access/src/main/java/org/springframework/security/web/access/channel/ChannelEntryPoint.java diff --git a/web/src/main/java/org/springframework/security/web/access/channel/ChannelProcessingFilter.java b/access/src/main/java/org/springframework/security/web/access/channel/ChannelProcessingFilter.java similarity index 100% rename from web/src/main/java/org/springframework/security/web/access/channel/ChannelProcessingFilter.java rename to access/src/main/java/org/springframework/security/web/access/channel/ChannelProcessingFilter.java diff --git a/web/src/main/java/org/springframework/security/web/access/channel/ChannelProcessor.java b/access/src/main/java/org/springframework/security/web/access/channel/ChannelProcessor.java similarity index 100% rename from web/src/main/java/org/springframework/security/web/access/channel/ChannelProcessor.java rename to access/src/main/java/org/springframework/security/web/access/channel/ChannelProcessor.java diff --git a/web/src/main/java/org/springframework/security/web/access/channel/InsecureChannelProcessor.java b/access/src/main/java/org/springframework/security/web/access/channel/InsecureChannelProcessor.java similarity index 100% rename from web/src/main/java/org/springframework/security/web/access/channel/InsecureChannelProcessor.java rename to access/src/main/java/org/springframework/security/web/access/channel/InsecureChannelProcessor.java diff --git a/web/src/main/java/org/springframework/security/web/access/channel/RetryWithHttpEntryPoint.java b/access/src/main/java/org/springframework/security/web/access/channel/RetryWithHttpEntryPoint.java similarity index 100% rename from web/src/main/java/org/springframework/security/web/access/channel/RetryWithHttpEntryPoint.java rename to access/src/main/java/org/springframework/security/web/access/channel/RetryWithHttpEntryPoint.java diff --git a/web/src/main/java/org/springframework/security/web/access/channel/RetryWithHttpsEntryPoint.java b/access/src/main/java/org/springframework/security/web/access/channel/RetryWithHttpsEntryPoint.java similarity index 100% rename from web/src/main/java/org/springframework/security/web/access/channel/RetryWithHttpsEntryPoint.java rename to access/src/main/java/org/springframework/security/web/access/channel/RetryWithHttpsEntryPoint.java diff --git a/web/src/main/java/org/springframework/security/web/access/channel/SecureChannelProcessor.java b/access/src/main/java/org/springframework/security/web/access/channel/SecureChannelProcessor.java similarity index 100% rename from web/src/main/java/org/springframework/security/web/access/channel/SecureChannelProcessor.java rename to access/src/main/java/org/springframework/security/web/access/channel/SecureChannelProcessor.java diff --git a/web/src/main/java/org/springframework/security/web/access/channel/package-info.java b/access/src/main/java/org/springframework/security/web/access/channel/package-info.java similarity index 100% rename from web/src/main/java/org/springframework/security/web/access/channel/package-info.java rename to access/src/main/java/org/springframework/security/web/access/channel/package-info.java diff --git a/web/src/main/java/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandler.java b/access/src/main/java/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandler.java similarity index 100% rename from web/src/main/java/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandler.java rename to access/src/main/java/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandler.java diff --git a/web/src/main/java/org/springframework/security/web/access/expression/ExpressionBasedFilterInvocationSecurityMetadataSource.java b/access/src/main/java/org/springframework/security/web/access/expression/ExpressionBasedFilterInvocationSecurityMetadataSource.java similarity index 100% rename from web/src/main/java/org/springframework/security/web/access/expression/ExpressionBasedFilterInvocationSecurityMetadataSource.java rename to access/src/main/java/org/springframework/security/web/access/expression/ExpressionBasedFilterInvocationSecurityMetadataSource.java diff --git a/web/src/main/java/org/springframework/security/web/access/expression/WebExpressionConfigAttribute.java b/access/src/main/java/org/springframework/security/web/access/expression/WebExpressionConfigAttribute.java similarity index 100% rename from web/src/main/java/org/springframework/security/web/access/expression/WebExpressionConfigAttribute.java rename to access/src/main/java/org/springframework/security/web/access/expression/WebExpressionConfigAttribute.java diff --git a/web/src/main/java/org/springframework/security/web/access/expression/WebExpressionVoter.java b/access/src/main/java/org/springframework/security/web/access/expression/WebExpressionVoter.java similarity index 100% rename from web/src/main/java/org/springframework/security/web/access/expression/WebExpressionVoter.java rename to access/src/main/java/org/springframework/security/web/access/expression/WebExpressionVoter.java diff --git a/web/src/main/java/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSource.java b/access/src/main/java/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSource.java similarity index 100% rename from web/src/main/java/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSource.java rename to access/src/main/java/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSource.java diff --git a/web/src/main/java/org/springframework/security/web/access/intercept/FilterInvocationSecurityMetadataSource.java b/access/src/main/java/org/springframework/security/web/access/intercept/FilterInvocationSecurityMetadataSource.java similarity index 100% rename from web/src/main/java/org/springframework/security/web/access/intercept/FilterInvocationSecurityMetadataSource.java rename to access/src/main/java/org/springframework/security/web/access/intercept/FilterInvocationSecurityMetadataSource.java diff --git a/web/src/main/java/org/springframework/security/web/access/intercept/FilterSecurityInterceptor.java b/access/src/main/java/org/springframework/security/web/access/intercept/FilterSecurityInterceptor.java similarity index 100% rename from web/src/main/java/org/springframework/security/web/access/intercept/FilterSecurityInterceptor.java rename to access/src/main/java/org/springframework/security/web/access/intercept/FilterSecurityInterceptor.java diff --git a/web/src/test/java/org/springframework/security/web/access/DefaultWebInvocationPrivilegeEvaluatorTests.java b/access/src/test/java/org/springframework/security/web/access/DefaultWebInvocationPrivilegeEvaluatorTests.java similarity index 72% rename from web/src/test/java/org/springframework/security/web/access/DefaultWebInvocationPrivilegeEvaluatorTests.java rename to access/src/test/java/org/springframework/security/web/access/DefaultWebInvocationPrivilegeEvaluatorTests.java index 4216da2869..3dd7f12d8e 100644 --- a/web/src/test/java/org/springframework/security/web/access/DefaultWebInvocationPrivilegeEvaluatorTests.java +++ b/access/src/test/java/org/springframework/security/web/access/DefaultWebInvocationPrivilegeEvaluatorTests.java @@ -16,9 +16,13 @@ package org.springframework.security.web.access; +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; +import org.mockito.ArgumentMatchers; +import org.mockito.BDDMockito; +import org.mockito.Mockito; import org.springframework.context.ApplicationEventPublisher; import org.springframework.mock.web.MockServletContext; @@ -33,15 +37,6 @@ import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyList; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.willThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - /** * Tests * {@link org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator}. @@ -61,43 +56,45 @@ public class DefaultWebInvocationPrivilegeEvaluatorTests { @BeforeEach public final void setUp() { this.interceptor = new FilterSecurityInterceptor(); - this.ods = mock(FilterInvocationSecurityMetadataSource.class); - this.adm = mock(AccessDecisionManager.class); - this.ram = mock(RunAsManager.class); - this.interceptor.setAuthenticationManager(mock(AuthenticationManager.class)); + this.ods = Mockito.mock(FilterInvocationSecurityMetadataSource.class); + this.adm = Mockito.mock(AccessDecisionManager.class); + this.ram = Mockito.mock(RunAsManager.class); + this.interceptor.setAuthenticationManager(Mockito.mock(AuthenticationManager.class)); this.interceptor.setSecurityMetadataSource(this.ods); this.interceptor.setAccessDecisionManager(this.adm); this.interceptor.setRunAsManager(this.ram); - this.interceptor.setApplicationEventPublisher(mock(ApplicationEventPublisher.class)); + this.interceptor.setApplicationEventPublisher(Mockito.mock(ApplicationEventPublisher.class)); SecurityContextHolder.clearContext(); } @Test public void permitsAccessIfNoMatchingAttributesAndPublicInvocationsAllowed() { DefaultWebInvocationPrivilegeEvaluator wipe = new DefaultWebInvocationPrivilegeEvaluator(this.interceptor); - given(this.ods.getAttributes(any())).willReturn(null); - assertThat(wipe.isAllowed("/context", "/foo/index.jsp", "GET", mock(Authentication.class))).isTrue(); + BDDMockito.given(this.ods.getAttributes(ArgumentMatchers.any())).willReturn(null); + Assertions.assertThat(wipe.isAllowed("/context", "/foo/index.jsp", "GET", Mockito.mock(Authentication.class))) + .isTrue(); } @Test public void deniesAccessIfNoMatchingAttributesAndPublicInvocationsNotAllowed() { DefaultWebInvocationPrivilegeEvaluator wipe = new DefaultWebInvocationPrivilegeEvaluator(this.interceptor); - given(this.ods.getAttributes(any())).willReturn(null); + BDDMockito.given(this.ods.getAttributes(ArgumentMatchers.any())).willReturn(null); this.interceptor.setRejectPublicInvocations(true); - assertThat(wipe.isAllowed("/context", "/foo/index.jsp", "GET", mock(Authentication.class))).isFalse(); + Assertions.assertThat(wipe.isAllowed("/context", "/foo/index.jsp", "GET", Mockito.mock(Authentication.class))) + .isFalse(); } @Test public void deniesAccessIfAuthenticationIsNull() { DefaultWebInvocationPrivilegeEvaluator wipe = new DefaultWebInvocationPrivilegeEvaluator(this.interceptor); - assertThat(wipe.isAllowed("/foo/index.jsp", null)).isFalse(); + Assertions.assertThat(wipe.isAllowed("/foo/index.jsp", null)).isFalse(); } @Test public void allowsAccessIfAccessDecisionManagerDoes() { Authentication token = new TestingAuthenticationToken("test", "Password", "MOCK_INDEX"); DefaultWebInvocationPrivilegeEvaluator wipe = new DefaultWebInvocationPrivilegeEvaluator(this.interceptor); - assertThat(wipe.isAllowed("/foo/index.jsp", token)).isTrue(); + Assertions.assertThat(wipe.isAllowed("/foo/index.jsp", token)).isTrue(); } @SuppressWarnings("unchecked") @@ -105,8 +102,10 @@ public class DefaultWebInvocationPrivilegeEvaluatorTests { public void deniesAccessIfAccessDecisionManagerDoes() { Authentication token = new TestingAuthenticationToken("test", "Password", "MOCK_INDEX"); DefaultWebInvocationPrivilegeEvaluator wipe = new DefaultWebInvocationPrivilegeEvaluator(this.interceptor); - willThrow(new AccessDeniedException("")).given(this.adm).decide(any(Authentication.class), any(), anyList()); - assertThat(wipe.isAllowed("/foo/index.jsp", token)).isFalse(); + BDDMockito.willThrow(new AccessDeniedException("")) + .given(this.adm) + .decide(ArgumentMatchers.any(Authentication.class), ArgumentMatchers.any(), ArgumentMatchers.anyList()); + Assertions.assertThat(wipe.isAllowed("/foo/index.jsp", token)).isFalse(); } @Test @@ -118,8 +117,9 @@ public class DefaultWebInvocationPrivilegeEvaluatorTests { DefaultWebInvocationPrivilegeEvaluator wipe = new DefaultWebInvocationPrivilegeEvaluator(this.interceptor); wipe.setServletContext(servletContext); wipe.isAllowed("/foo/index.jsp", token); - verify(this.adm).decide(eq(token), filterInvocationArgumentCaptor.capture(), any()); - assertThat(filterInvocationArgumentCaptor.getValue().getRequest().getServletContext()).isNotNull(); + Mockito.verify(this.adm) + .decide(ArgumentMatchers.eq(token), filterInvocationArgumentCaptor.capture(), ArgumentMatchers.any()); + Assertions.assertThat(filterInvocationArgumentCaptor.getValue().getRequest().getServletContext()).isNotNull(); } } diff --git a/web/src/test/java/org/springframework/security/web/access/channel/ChannelDecisionManagerImplTests.java b/access/src/test/java/org/springframework/security/web/access/channel/ChannelDecisionManagerImplTests.java similarity index 96% rename from web/src/test/java/org/springframework/security/web/access/channel/ChannelDecisionManagerImplTests.java rename to access/src/test/java/org/springframework/security/web/access/channel/ChannelDecisionManagerImplTests.java index 4ab06ff409..e550801303 100644 --- a/web/src/test/java/org/springframework/security/web/access/channel/ChannelDecisionManagerImplTests.java +++ b/access/src/test/java/org/springframework/security/web/access/channel/ChannelDecisionManagerImplTests.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.Vector; import jakarta.servlet.FilterChain; +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.mock.web.MockHttpServletRequest; @@ -85,7 +86,7 @@ public class ChannelDecisionManagerImplTests { FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class)); List cad = SecurityConfig.createList("xyz"); cdm.decide(fi, cad); - assertThat(fi.getResponse().isCommitted()).isTrue(); + Assertions.assertThat(fi.getResponse().isCommitted()).isTrue(); } @Test @@ -100,7 +101,7 @@ public class ChannelDecisionManagerImplTests { MockHttpServletResponse response = new MockHttpServletResponse(); FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class)); cdm.decide(fi, SecurityConfig.createList(new String[] { "abc", "ANY_CHANNEL" })); - assertThat(fi.getResponse().isCommitted()).isFalse(); + Assertions.assertThat(fi.getResponse().isCommitted()).isFalse(); } @Test @@ -117,7 +118,7 @@ public class ChannelDecisionManagerImplTests { MockHttpServletResponse response = new MockHttpServletResponse(); FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class)); cdm.decide(fi, SecurityConfig.createList("SOME_ATTRIBUTE_NO_PROCESSORS_SUPPORT")); - assertThat(fi.getResponse().isCommitted()).isFalse(); + Assertions.assertThat(fi.getResponse().isCommitted()).isFalse(); } @Test diff --git a/web/src/test/java/org/springframework/security/web/access/channel/ChannelProcessingFilterTests.java b/access/src/test/java/org/springframework/security/web/access/channel/ChannelProcessingFilterTests.java similarity index 95% rename from web/src/test/java/org/springframework/security/web/access/channel/ChannelProcessingFilterTests.java rename to access/src/test/java/org/springframework/security/web/access/channel/ChannelProcessingFilterTests.java index ad3f3afa66..d486d36189 100644 --- a/web/src/test/java/org/springframework/security/web/access/channel/ChannelProcessingFilterTests.java +++ b/access/src/test/java/org/springframework/security/web/access/channel/ChannelProcessingFilterTests.java @@ -28,11 +28,11 @@ import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.SecurityConfig; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; +import org.springframework.security.web.servlet.TestMockHttpServletRequests; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.mockito.Mockito.mock; -import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * Tests {@link ChannelProcessingFilter}. @@ -82,7 +82,7 @@ public class ChannelProcessingFilterTests { filter.setChannelDecisionManager(new MockChannelDecisionManager(true, "SOME_ATTRIBUTE")); MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "SOME_ATTRIBUTE"); filter.setSecurityMetadataSource(fids); - MockHttpServletRequest request = get("/path").build(); + MockHttpServletRequest request = TestMockHttpServletRequests.get("/path").build(); request.setQueryString("info=now"); MockHttpServletResponse response = new MockHttpServletResponse(); filter.doFilter(request, response, mock(FilterChain.class)); @@ -94,7 +94,7 @@ public class ChannelProcessingFilterTests { filter.setChannelDecisionManager(new MockChannelDecisionManager(false, "SOME_ATTRIBUTE")); MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "SOME_ATTRIBUTE"); filter.setSecurityMetadataSource(fids); - MockHttpServletRequest request = get("/path").build(); + MockHttpServletRequest request = TestMockHttpServletRequests.get("/path").build(); request.setQueryString("info=now"); MockHttpServletResponse response = new MockHttpServletResponse(); filter.doFilter(request, response, mock(FilterChain.class)); @@ -106,7 +106,7 @@ public class ChannelProcessingFilterTests { filter.setChannelDecisionManager(new MockChannelDecisionManager(false, "NOT_USED")); MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "NOT_USED"); filter.setSecurityMetadataSource(fids); - MockHttpServletRequest request = get("/PATH_NOT_MATCHING_CONFIG_ATTRIBUTE").build(); + MockHttpServletRequest request = TestMockHttpServletRequests.get("/PATH_NOT_MATCHING_CONFIG_ATTRIBUTE").build(); request.setQueryString("info=now"); MockHttpServletResponse response = new MockHttpServletResponse(); filter.doFilter(request, response, mock(FilterChain.class)); diff --git a/web/src/test/java/org/springframework/security/web/access/channel/InsecureChannelProcessorTests.java b/access/src/test/java/org/springframework/security/web/access/channel/InsecureChannelProcessorTests.java similarity index 88% rename from web/src/test/java/org/springframework/security/web/access/channel/InsecureChannelProcessorTests.java rename to access/src/test/java/org/springframework/security/web/access/channel/InsecureChannelProcessorTests.java index 1c290cac06..6b4f1d8bae 100644 --- a/web/src/test/java/org/springframework/security/web/access/channel/InsecureChannelProcessorTests.java +++ b/access/src/test/java/org/springframework/security/web/access/channel/InsecureChannelProcessorTests.java @@ -17,17 +17,18 @@ package org.springframework.security.web.access.channel; import jakarta.servlet.FilterChain; +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.security.access.SecurityConfig; import org.springframework.security.web.FilterInvocation; +import org.springframework.security.web.servlet.TestMockHttpServletRequests; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.mockito.Mockito.mock; -import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * Tests {@link InsecureChannelProcessor}. @@ -38,19 +39,21 @@ public class InsecureChannelProcessorTests { @Test public void testDecideDetectsAcceptableChannel() throws Exception { - MockHttpServletRequest request = get("http://localhost:8080").requestUri("/bigapp", "/servlet", null) + MockHttpServletRequest request = TestMockHttpServletRequests.get("http://localhost:8080") + .requestUri("/bigapp", "/servlet", null) .queryString("info=true") .build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class)); InsecureChannelProcessor processor = new InsecureChannelProcessor(); processor.decide(fi, SecurityConfig.createList("SOME_IGNORED_ATTRIBUTE", "REQUIRES_INSECURE_CHANNEL")); - assertThat(fi.getResponse().isCommitted()).isFalse(); + Assertions.assertThat(fi.getResponse().isCommitted()).isFalse(); } @Test public void testDecideDetectsUnacceptableChannel() throws Exception { - MockHttpServletRequest request = get("https://localhost:8443").requestUri("/bigapp", "/servlet", null) + MockHttpServletRequest request = TestMockHttpServletRequests.get("https://localhost:8443") + .requestUri("/bigapp", "/servlet", null) .queryString("info=true") .build(); MockHttpServletResponse response = new MockHttpServletResponse(); @@ -58,7 +61,7 @@ public class InsecureChannelProcessorTests { InsecureChannelProcessor processor = new InsecureChannelProcessor(); processor.decide(fi, SecurityConfig.createList(new String[] { "SOME_IGNORED_ATTRIBUTE", "REQUIRES_INSECURE_CHANNEL" })); - assertThat(fi.getResponse().isCommitted()).isTrue(); + Assertions.assertThat(fi.getResponse().isCommitted()).isTrue(); } @Test diff --git a/web/src/test/java/org/springframework/security/web/access/channel/RetryWithHttpEntryPointTests.java b/access/src/test/java/org/springframework/security/web/access/channel/RetryWithHttpEntryPointTests.java similarity index 100% rename from web/src/test/java/org/springframework/security/web/access/channel/RetryWithHttpEntryPointTests.java rename to access/src/test/java/org/springframework/security/web/access/channel/RetryWithHttpEntryPointTests.java diff --git a/web/src/test/java/org/springframework/security/web/access/channel/RetryWithHttpsEntryPointTests.java b/access/src/test/java/org/springframework/security/web/access/channel/RetryWithHttpsEntryPointTests.java similarity index 100% rename from web/src/test/java/org/springframework/security/web/access/channel/RetryWithHttpsEntryPointTests.java rename to access/src/test/java/org/springframework/security/web/access/channel/RetryWithHttpsEntryPointTests.java diff --git a/web/src/test/java/org/springframework/security/web/access/channel/SecureChannelProcessorTests.java b/access/src/test/java/org/springframework/security/web/access/channel/SecureChannelProcessorTests.java similarity index 88% rename from web/src/test/java/org/springframework/security/web/access/channel/SecureChannelProcessorTests.java rename to access/src/test/java/org/springframework/security/web/access/channel/SecureChannelProcessorTests.java index 4263cec233..f67d0ae7b3 100644 --- a/web/src/test/java/org/springframework/security/web/access/channel/SecureChannelProcessorTests.java +++ b/access/src/test/java/org/springframework/security/web/access/channel/SecureChannelProcessorTests.java @@ -17,17 +17,18 @@ package org.springframework.security.web.access.channel; import jakarta.servlet.FilterChain; +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.security.access.SecurityConfig; import org.springframework.security.web.FilterInvocation; +import org.springframework.security.web.servlet.TestMockHttpServletRequests; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.mockito.Mockito.mock; -import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * Tests {@link SecureChannelProcessor}. @@ -38,19 +39,21 @@ public class SecureChannelProcessorTests { @Test public void testDecideDetectsAcceptableChannel() throws Exception { - MockHttpServletRequest request = get("https://localhost:8443").requestUri("/bigapp", "/servlet", null) + MockHttpServletRequest request = TestMockHttpServletRequests.get("https://localhost:8443") + .requestUri("/bigapp", "/servlet", null) .queryString("info=true") .build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class)); SecureChannelProcessor processor = new SecureChannelProcessor(); processor.decide(fi, SecurityConfig.createList("SOME_IGNORED_ATTRIBUTE", "REQUIRES_SECURE_CHANNEL")); - assertThat(fi.getResponse().isCommitted()).isFalse(); + Assertions.assertThat(fi.getResponse().isCommitted()).isFalse(); } @Test public void testDecideDetectsUnacceptableChannel() throws Exception { - MockHttpServletRequest request = get("http://localhost:8080").requestUri("/bigapp", "/servlet", null) + MockHttpServletRequest request = TestMockHttpServletRequests.get("http://localhost:8080") + .requestUri("/bigapp", "/servlet", null) .queryString("info=true") .build(); MockHttpServletResponse response = new MockHttpServletResponse(); @@ -58,7 +61,7 @@ public class SecureChannelProcessorTests { SecureChannelProcessor processor = new SecureChannelProcessor(); processor.decide(fi, SecurityConfig.createList(new String[] { "SOME_IGNORED_ATTRIBUTE", "REQUIRES_SECURE_CHANNEL" })); - assertThat(fi.getResponse().isCommitted()).isTrue(); + Assertions.assertThat(fi.getResponse().isCommitted()).isTrue(); } @Test diff --git a/web/src/test/java/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandlerTests.java b/access/src/test/java/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandlerTests.java similarity index 100% rename from web/src/test/java/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandlerTests.java rename to access/src/test/java/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandlerTests.java diff --git a/web/src/test/java/org/springframework/security/web/access/expression/ExpressionBasedFilterInvocationSecurityMetadataSourceTests.java b/access/src/test/java/org/springframework/security/web/access/expression/ExpressionBasedFilterInvocationSecurityMetadataSourceTests.java similarity index 100% rename from web/src/test/java/org/springframework/security/web/access/expression/ExpressionBasedFilterInvocationSecurityMetadataSourceTests.java rename to access/src/test/java/org/springframework/security/web/access/expression/ExpressionBasedFilterInvocationSecurityMetadataSourceTests.java diff --git a/web/src/test/java/org/springframework/security/web/access/expression/WebExpressionVoterTests.java b/access/src/test/java/org/springframework/security/web/access/expression/WebExpressionVoterTests.java similarity index 100% rename from web/src/test/java/org/springframework/security/web/access/expression/WebExpressionVoterTests.java rename to access/src/test/java/org/springframework/security/web/access/expression/WebExpressionVoterTests.java diff --git a/web/src/test/java/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSourceTests.java b/access/src/test/java/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSourceTests.java similarity index 90% rename from web/src/test/java/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSourceTests.java rename to access/src/test/java/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSourceTests.java index dd746f35a6..3de762fd5e 100644 --- a/web/src/test/java/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSourceTests.java +++ b/access/src/test/java/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSourceTests.java @@ -28,12 +28,12 @@ import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.SecurityConfig; import org.springframework.security.web.FilterInvocation; +import org.springframework.security.web.servlet.TestMockHttpServletRequests; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; -import static org.springframework.security.web.servlet.TestMockHttpServletRequests.request; -import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern; /** * Tests {@link DefaultFilterInvocationSecurityMetadataSource}. @@ -48,7 +48,7 @@ public class DefaultFilterInvocationSecurityMetadataSourceTests { private void createFids(String pattern, HttpMethod method) { LinkedHashMap> requestMap = new LinkedHashMap<>(); - requestMap.put(pathPattern(method, pattern), this.def); + requestMap.put(PathPatternRequestMatcher.pathPattern(method, pattern), this.def); this.fids = new DefaultFilterInvocationSecurityMetadataSource(requestMap); } @@ -117,8 +117,9 @@ public class DefaultFilterInvocationSecurityMetadataSourceTests { public void mixingPatternsWithAndWithoutHttpMethodsIsSupported() { LinkedHashMap> requestMap = new LinkedHashMap<>(); Collection userAttrs = SecurityConfig.createList("A"); - requestMap.put(pathPattern("/user/**"), userAttrs); - requestMap.put(pathPattern(HttpMethod.GET, "/teller/**"), SecurityConfig.createList("B")); + requestMap.put(PathPatternRequestMatcher.pathPattern("/user/**"), userAttrs); + requestMap.put(PathPatternRequestMatcher.pathPattern(HttpMethod.GET, "/teller/**"), + SecurityConfig.createList("B")); this.fids = new DefaultFilterInvocationSecurityMetadataSource(requestMap); FilterInvocation fi = createFilterInvocation("/user", null, null, "GET"); Collection attrs = this.fids.getAttributes(fi); @@ -141,7 +142,8 @@ public class DefaultFilterInvocationSecurityMetadataSourceTests { private FilterInvocation createFilterInvocation(String servletPath, String pathInfo, String queryString, String method) { - MockHttpServletRequest request = request(method).requestUri(null, servletPath, pathInfo) + MockHttpServletRequest request = TestMockHttpServletRequests.request(method) + .requestUri(null, servletPath, pathInfo) .queryString(queryString) .build(); return new FilterInvocation(request, new MockHttpServletResponse(), mock(FilterChain.class)); diff --git a/web/src/test/java/org/springframework/security/web/access/intercept/FilterSecurityInterceptorTests.java b/access/src/test/java/org/springframework/security/web/access/intercept/FilterSecurityInterceptorTests.java similarity index 97% rename from web/src/test/java/org/springframework/security/web/access/intercept/FilterSecurityInterceptorTests.java rename to access/src/test/java/org/springframework/security/web/access/intercept/FilterSecurityInterceptorTests.java index 77370b0cd7..5194c38325 100644 --- a/web/src/test/java/org/springframework/security/web/access/intercept/FilterSecurityInterceptorTests.java +++ b/access/src/test/java/org/springframework/security/web/access/intercept/FilterSecurityInterceptorTests.java @@ -39,6 +39,7 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.FilterInvocation; +import org.springframework.security.web.servlet.TestMockHttpServletRequests; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -53,7 +54,6 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * Tests {@link FilterSecurityInterceptor}. @@ -189,7 +189,7 @@ public class FilterSecurityInterceptorTests { private FilterInvocation createinvocation() { MockHttpServletResponse response = new MockHttpServletResponse(); - MockHttpServletRequest request = get("/secure/page.html").build(); + MockHttpServletRequest request = TestMockHttpServletRequests.get("/secure/page.html").build(); FilterChain chain = mock(FilterChain.class); FilterInvocation fi = new FilterInvocation(request, response, chain); return fi; diff --git a/taglibs/spring-security-taglibs.gradle b/taglibs/spring-security-taglibs.gradle index 7ef22c9819..875bf8220a 100644 --- a/taglibs/spring-security-taglibs.gradle +++ b/taglibs/spring-security-taglibs.gradle @@ -21,6 +21,7 @@ dependencies { testRuntimeOnly 'jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api' + testImplementation project(':spring-security-access') testImplementation "org.assertj:assertj-core" testImplementation "org.junit.jupiter:junit-jupiter-api" testImplementation "org.junit.jupiter:junit-jupiter-params" diff --git a/web/spring-security-web.gradle b/web/spring-security-web.gradle index d4113fed83..87ce691e0c 100644 --- a/web/spring-security-web.gradle +++ b/web/spring-security-web.gradle @@ -39,7 +39,6 @@ dependencies { api 'org.springframework:spring-expression' api 'org.springframework:spring-web' - optional project(':spring-security-access') optional 'com.fasterxml.jackson.core:jackson-databind' optional 'io.micrometer:context-propagation' optional 'io.projectreactor:reactor-core' diff --git a/web/src/test/java/org/springframework/security/web/access/expression/DefaultHttpSecurityExpressionHandlerTests.java b/web/src/test/java/org/springframework/security/web/access/expression/DefaultHttpSecurityExpressionHandlerTests.java index 9184d92217..8643754779 100644 --- a/web/src/test/java/org/springframework/security/web/access/expression/DefaultHttpSecurityExpressionHandlerTests.java +++ b/web/src/test/java/org/springframework/security/web/access/expression/DefaultHttpSecurityExpressionHandlerTests.java @@ -32,10 +32,10 @@ import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; import org.springframework.expression.ExpressionParser; import org.springframework.expression.TypedValue; -import org.springframework.security.access.SecurityConfig; import org.springframework.security.access.expression.SecurityExpressionRoot; import org.springframework.security.authentication.AuthenticationTrustResolver; import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.access.intercept.RequestAuthorizationContext; @@ -73,15 +73,15 @@ public class DefaultHttpSecurityExpressionHandlerTests { @Test public void expressionPropertiesAreResolvedAgainstAppContextBeans() { StaticApplicationContext appContext = new StaticApplicationContext(); - RootBeanDefinition bean = new RootBeanDefinition(SecurityConfig.class); + RootBeanDefinition bean = new RootBeanDefinition(SimpleGrantedAuthority.class); bean.getConstructorArgumentValues().addGenericArgumentValue("ROLE_A"); appContext.registerBeanDefinition("role", bean); this.handler.setApplicationContext(appContext); EvaluationContext ctx = this.handler.createEvaluationContext(mock(Authentication.class), mock(RequestAuthorizationContext.class)); ExpressionParser parser = this.handler.getExpressionParser(); - assertThat(parser.parseExpression("@role.getAttribute() == 'ROLE_A'").getValue(ctx, Boolean.class)).isTrue(); - assertThat(parser.parseExpression("@role.attribute == 'ROLE_A'").getValue(ctx, Boolean.class)).isTrue(); + assertThat(parser.parseExpression("@role.getAuthority() == 'ROLE_A'").getValue(ctx, Boolean.class)).isTrue(); + assertThat(parser.parseExpression("@role.authority == 'ROLE_A'").getValue(ctx, Boolean.class)).isTrue(); } @Test From 505631d7c62d1dd88a916b4507c67bdd6575318c Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Tue, 2 Sep 2025 16:30:26 -0600 Subject: [PATCH 5/6] Move Acl Access API Issue gh-17847 --- access/spring-security-access.gradle | 1 + .../java/org/springframework/security/acls/AclEntryVoter.java | 0 .../security/acls/afterinvocation/AbstractAclProvider.java | 0 .../AclEntryAfterInvocationCollectionFilteringProvider.java | 0 .../acls/afterinvocation/AclEntryAfterInvocationProvider.java | 0 .../security/acls/afterinvocation/ArrayFilterer.java | 0 .../security/acls/afterinvocation/CollectionFilterer.java | 0 .../springframework/security/acls/afterinvocation/Filterer.java | 0 .../security/acls/afterinvocation/package-info.java | 0 ...AclEntryAfterInvocationCollectionFilteringProviderTests.java | 0 .../afterinvocation/AclEntryAfterInvocationProviderTests.java | 0 acl/spring-security-acl.gradle | 2 -- 12 files changed, 1 insertion(+), 2 deletions(-) rename {acl => access}/src/main/java/org/springframework/security/acls/AclEntryVoter.java (100%) rename {acl => access}/src/main/java/org/springframework/security/acls/afterinvocation/AbstractAclProvider.java (100%) rename {acl => access}/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProvider.java (100%) rename {acl => access}/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProvider.java (100%) rename {acl => access}/src/main/java/org/springframework/security/acls/afterinvocation/ArrayFilterer.java (100%) rename {acl => access}/src/main/java/org/springframework/security/acls/afterinvocation/CollectionFilterer.java (100%) rename {acl => access}/src/main/java/org/springframework/security/acls/afterinvocation/Filterer.java (100%) rename {acl => access}/src/main/java/org/springframework/security/acls/afterinvocation/package-info.java (100%) rename {acl => access}/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProviderTests.java (100%) rename {acl => access}/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProviderTests.java (100%) diff --git a/access/spring-security-access.gradle b/access/spring-security-access.gradle index cf176ec074..f5747c6686 100644 --- a/access/spring-security-access.gradle +++ b/access/spring-security-access.gradle @@ -11,6 +11,7 @@ dependencies { api 'org.springframework:spring-expression' api 'io.micrometer:micrometer-observation' + optional project(':spring-security-acl') optional project(':spring-security-messaging') optional project(':spring-security-web') optional 'org.springframework:spring-websocket' diff --git a/acl/src/main/java/org/springframework/security/acls/AclEntryVoter.java b/access/src/main/java/org/springframework/security/acls/AclEntryVoter.java similarity index 100% rename from acl/src/main/java/org/springframework/security/acls/AclEntryVoter.java rename to access/src/main/java/org/springframework/security/acls/AclEntryVoter.java diff --git a/acl/src/main/java/org/springframework/security/acls/afterinvocation/AbstractAclProvider.java b/access/src/main/java/org/springframework/security/acls/afterinvocation/AbstractAclProvider.java similarity index 100% rename from acl/src/main/java/org/springframework/security/acls/afterinvocation/AbstractAclProvider.java rename to access/src/main/java/org/springframework/security/acls/afterinvocation/AbstractAclProvider.java diff --git a/acl/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProvider.java b/access/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProvider.java similarity index 100% rename from acl/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProvider.java rename to access/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProvider.java diff --git a/acl/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProvider.java b/access/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProvider.java similarity index 100% rename from acl/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProvider.java rename to access/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProvider.java diff --git a/acl/src/main/java/org/springframework/security/acls/afterinvocation/ArrayFilterer.java b/access/src/main/java/org/springframework/security/acls/afterinvocation/ArrayFilterer.java similarity index 100% rename from acl/src/main/java/org/springframework/security/acls/afterinvocation/ArrayFilterer.java rename to access/src/main/java/org/springframework/security/acls/afterinvocation/ArrayFilterer.java diff --git a/acl/src/main/java/org/springframework/security/acls/afterinvocation/CollectionFilterer.java b/access/src/main/java/org/springframework/security/acls/afterinvocation/CollectionFilterer.java similarity index 100% rename from acl/src/main/java/org/springframework/security/acls/afterinvocation/CollectionFilterer.java rename to access/src/main/java/org/springframework/security/acls/afterinvocation/CollectionFilterer.java diff --git a/acl/src/main/java/org/springframework/security/acls/afterinvocation/Filterer.java b/access/src/main/java/org/springframework/security/acls/afterinvocation/Filterer.java similarity index 100% rename from acl/src/main/java/org/springframework/security/acls/afterinvocation/Filterer.java rename to access/src/main/java/org/springframework/security/acls/afterinvocation/Filterer.java diff --git a/acl/src/main/java/org/springframework/security/acls/afterinvocation/package-info.java b/access/src/main/java/org/springframework/security/acls/afterinvocation/package-info.java similarity index 100% rename from acl/src/main/java/org/springframework/security/acls/afterinvocation/package-info.java rename to access/src/main/java/org/springframework/security/acls/afterinvocation/package-info.java diff --git a/acl/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProviderTests.java b/access/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProviderTests.java similarity index 100% rename from acl/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProviderTests.java rename to access/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProviderTests.java diff --git a/acl/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProviderTests.java b/access/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProviderTests.java similarity index 100% rename from acl/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProviderTests.java rename to access/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProviderTests.java diff --git a/acl/spring-security-acl.gradle b/acl/spring-security-acl.gradle index 0238984aab..ec3d59bbe7 100644 --- a/acl/spring-security-acl.gradle +++ b/acl/spring-security-acl.gradle @@ -9,8 +9,6 @@ dependencies { api 'org.springframework:spring-jdbc' api 'org.springframework:spring-tx' - optional project(':spring-security-access') - testImplementation "org.assertj:assertj-core" testImplementation "org.junit.jupiter:junit-jupiter-api" testImplementation "org.junit.jupiter:junit-jupiter-params" From b87d63cb7117c5db9e37ca33798fefd15fe90046 Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Tue, 2 Sep 2025 18:48:37 -0600 Subject: [PATCH 6/6] Document spring-security-access Closes gh-17847 --- docs/modules/ROOT/nav.adoc | 1 + .../migration/servlet/authorization.adoc | 29 +++++++++++++++++ .../ROOT/pages/servlet/appendix/faq.adoc | 25 ++++++++------- .../appendix/namespace/method-security.adoc | 32 +++++++++++++++++-- .../pages/servlet/authorization/acls.adoc | 11 +++++-- .../servlet/authorization/architecture.adoc | 24 +++++++++++++- .../pages/servlet/authorization/index.adoc | 7 ++++ .../authorization/method-security.adoc | 22 +++++++++++++ docs/modules/ROOT/pages/whats-new.adoc | 1 + 9 files changed, 134 insertions(+), 18 deletions(-) create mode 100644 docs/modules/ROOT/pages/migration/servlet/authorization.adoc diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 65e88a720e..f5b1816e3d 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -5,6 +5,7 @@ * xref:migration-8/index.adoc[Preparing for 8.0] * xref:migration/index.adoc[Migrating to 7] ** xref:migration/servlet/index.adoc[Servlet] +*** xref:migration/servlet/authorization.adoc[Authorization] *** xref:migration/servlet/oauth2.adoc[OAuth 2.0] *** xref:migration/servlet/saml2.adoc[SAML 2.0] ** xref:migration/reactive.adoc[Reactive] diff --git a/docs/modules/ROOT/pages/migration/servlet/authorization.adoc b/docs/modules/ROOT/pages/migration/servlet/authorization.adoc new file mode 100644 index 0000000000..b34cc5fe3f --- /dev/null +++ b/docs/modules/ROOT/pages/migration/servlet/authorization.adoc @@ -0,0 +1,29 @@ += Authorization Changes + +== If Using Access API, Add `spring-security-access` + +Spring Security 7 moves `AccessDecisionManager`, `AccessDecisionVoter`, and the related Access API to a legacy module, `spring-security-access`. +The Access API is deprecated in favor of the Authorization API as of Spring Security 5. + +You can add the dependency like other Spring Security dependencies like so: + +[tabs] +====== +Maven:: ++ +[source,xml,role="primary"] +---- + + org.springframework.security + spring-security-access + +---- + +Gradle:: ++ +[source,groovy,role="primary"] +---- +implementation('org.springframework.security:spring-security-access') +---- +====== + diff --git a/docs/modules/ROOT/pages/servlet/appendix/faq.adoc b/docs/modules/ROOT/pages/servlet/appendix/faq.adoc index a47f591869..d05269049a 100644 --- a/docs/modules/ROOT/pages/servlet/appendix/faq.adoc +++ b/docs/modules/ROOT/pages/servlet/appendix/faq.adoc @@ -138,12 +138,13 @@ If you use hashed passwords, make sure the value stored in your database is _exa === My application goes into an "`endless loop`" when I try to log in. What is going on? A common user problem with infinite loop and redirecting to the login page is caused by accidentally configuring the login page as a "`secured`" resource. -Make sure your configuration allows anonymous access to the login page, either by excluding it from the security filter chain or marking it as requiring `ROLE_ANONYMOUS`. - -If your `AccessDecisionManager` includes an `AuthenticatedVoter`, you can use the `IS_AUTHENTICATED_ANONYMOUSLY` attribute. This is automatically available if you use the standard namespace configuration setup. - -From Spring Security 2.0.1 onwards, when you use namespace-based configuration, a check is made on loading the application context and a warning message logged if your login page appears to be protected. +Make sure your configuration allows anonymous access to the login page. +You can do so with the xref:servlet/authorization/authorize-http-requests.adoc[`authorizeHttpRequests`] DSL. +[TIP] +==== +When you use namespace- or DSL-based configuration, a check is made on loading the application context and a warning message logged if your login page appears to be protected. +==== [[appendix-faq-anon-access-denied]] === I get an exception with the message "Access is denied (user is anonymous);". What's wrong? @@ -382,16 +383,16 @@ You should probably read the chapters on namespace parsing in the standard Sprin [[appendix-faq-role-prefix]] -=== What does "ROLE_" mean and why do I need it on my role names? +=== What does "ROLE_" mean? -Spring Security has a voter-based architecture, which means that an access decision is made by a series of `AccessDecisionVoter` instances. -The voters act on the "`configuration attributes`", which are specified for a secured resource (such as a method invocation). With this approach, not all attributes may be relevant to all voters, and a voter needs to know when it should ignore an attribute (abstain) and when it should vote to grant or deny access based on the attribute value. -The most common voter is the `RoleVoter`, which, by default, votes whenever it finds an attribute with the `ROLE_` prefix. -It makes a simple comparison of the attribute (such as `ROLE_USER`) with the names of the authorities that the current user has been assigned. -If it finds a match (they have an authority called `ROLE_USER`), it votes to grant access. Otherwise, it votes to deny access. +`ROLE_` is a way to identify the nature of a given authority. +An authority prefixed by `ROLE_` means that this authority is a role, likely derived from an RBAC authorization model. -You can change the prefix by setting the `rolePrefix` property of `RoleVoter`. If you need only to use roles in your application and have no need for other custom voters, you can set the prefix to a blank string. In that case, the `RoleVoter` treats all attributes as roles. +Having a prefix allows for clear differentiation from OAuth 2.0 scopes (which use `SCOPE_`) and authorities granted from other sources as well. +You may choose to not prefix your authorities. +Modern Spring Security authorization components either allow you to supply the entire authority name, rendering the prefix unnecessary. +An example of this is how xref:servlet/authorization/authorize-http-requests.adoc[`authorizeHttpRequests`] and xref:servlet/authorization/method-security.adoc[`@PreAuthorize`] allow you to call `hasAuthority` or `hasRole`. [[appendix-faq-what-dependencies]] === How do I know which dependencies to add to my application to work with Spring Security? diff --git a/docs/modules/ROOT/pages/servlet/appendix/namespace/method-security.adoc b/docs/modules/ROOT/pages/servlet/appendix/namespace/method-security.adoc index 420a34c828..477d5d1e30 100644 --- a/docs/modules/ROOT/pages/servlet/appendix/namespace/method-security.adoc +++ b/docs/modules/ROOT/pages/servlet/appendix/namespace/method-security.adoc @@ -56,6 +56,11 @@ Methods can be secured by the use of annotations (defined at the interface or cl [[nsa-global-method-security-attributes]] === Attributes +[NOTE] +===== +`` is deprecated in favor of ``. +If you need to use ``, please include the `spring-security-access` dependency in your build configuration. +===== [[nsa-global-method-security-access-decision-manager-ref]] * **access-decision-manager-ref** @@ -145,6 +150,11 @@ You can define zero or more of these within the `global-method-security` element [[nsa-after-invocation-provider-attributes]] === Attributes +[NOTE] +===== +`` is deprecated in favor of `` and xref:servlet/authorization/method-security.adoc[`@PostFilter` and `@PostAuthorize`]. +If you need to use ``, please include the `spring-security-access` dependency in your build configuration while planning to migrate to a modern option. +===== [[nsa-after-invocation-provider-ref]] * **ref** @@ -179,6 +189,11 @@ Only applies if these annotations are enabled. == Defines the PrePostInvocationAttributeFactory instance which is used to generate pre and post invocation metadata from the annotated methods. +[NOTE] +===== +`` is deprecated in favor of `` and xref:servlet/authorization/method-security.adoc[`@PostFilter` and `@PostAuthorize`]. +If you need to use ``, please include the `spring-security-access` dependency in your build configuration while planning to migrate to a modern option. +===== [[nsa-invocation-attribute-factory-parents]] === Parent Elements of @@ -201,6 +216,11 @@ Defines a reference to a Spring bean Id. == Customizes the `PostInvocationAdviceProvider` with the ref as the `PostInvocationAuthorizationAdvice` for the element. +[NOTE] +===== +`` is deprecated in favor of `` and xref:servlet/authorization/method-security.adoc[`@PostFilter` and `@PostAuthorize`]. +If you need to use ``, please include the `spring-security-access` dependency in your build configuration while planning to migrate to a modern option. +===== [[nsa-post-invocation-advice-parents]] === Parent Elements of @@ -223,6 +243,11 @@ Defines a reference to a Spring bean Id. == Customizes the `PreInvocationAuthorizationAdviceVoter` with the ref as the `PreInvocationAuthorizationAdviceVoter` for the element. +[NOTE] +===== +`` is deprecated in favor of `` and xref:servlet/authorization/method-security.adoc[`@PreFilter` and `@PreAuthorize`]. +If you need to use ``, please include the `spring-security-access` dependency in your build configuration while planning to migrate to a modern option. +===== [[nsa-pre-invocation-advice-parents]] === Parent Elements of @@ -247,7 +272,6 @@ Defines a reference to a Spring bean Id. Rather than defining security attributes on an individual method or class basis using the `@Secured` annotation, you can define cross-cutting security constraints across whole sets of methods and interfaces in your service layer using the `` element. You can find an example in the xref:servlet/authorization/method-security.adoc#ns-protect-pointcut[namespace introduction]. - [[nsa-protect-pointcut-parents]] === Parent Elements of @@ -293,7 +317,6 @@ Optional AuthorizationManager bean ID to be used instead of the default (superse * **access-decision-manager-ref** Optional AccessDecisionManager bean ID to be used by the created method security interceptor. - [[nsa-intercept-methods-children]] === Child Elements of @@ -306,6 +329,11 @@ Optional AccessDecisionManager bean ID to be used by the created method security == Creates a MethodSecurityMetadataSource instance +[NOTE] +===== +`` is deprecated in favor of xref:servlet/authorization/method-security.adoc[``]. +If you need to use ``, please include the `spring-security-access` dependency in your build configuration while planning to migrate to a modern option. +===== [[nsa-method-security-metadata-source-attributes]] === Attributes diff --git a/docs/modules/ROOT/pages/servlet/authorization/acls.adoc b/docs/modules/ROOT/pages/servlet/authorization/acls.adoc index 314d524be2..f36972f5cc 100644 --- a/docs/modules/ROOT/pages/servlet/authorization/acls.adoc +++ b/docs/modules/ROOT/pages/servlet/authorization/acls.adoc @@ -17,9 +17,9 @@ When you use Spring Security as the foundation, you have several possible approa * Write your business methods to enforce the security. You could consult a collection within the `Customer` domain object instance to determine which users have access. By using `SecurityContextHolder.getContext().getAuthentication()`, you can access the `Authentication` object. -* Write an `AccessDecisionVoter` to enforce the security from the `GrantedAuthority[]` instances stored in the `Authentication` object. +* Write an `AuthorizationManager` to enforce the security from the `GrantedAuthority[]` instances stored in the `Authentication` object. This means that your `AuthenticationManager` needs to populate the `Authentication` with custom `GrantedAuthority[]` objects to represent each of the `Customer` domain object instances to which the principal has access. -* Write an `AccessDecisionVoter` to enforce the security and open the target `Customer` domain object directly. +* Write an `AuthorizationManager` to enforce the security and open the target `Customer` domain object directly. This would mean your voter needs access to a DAO that lets it retrieve the `Customer` object. It can then access the `Customer` object's collection of approved users and make the appropriate decision. @@ -29,7 +29,7 @@ The main problems with this include the enhanced difficulty of unit testing and Obtaining the `GrantedAuthority[]` instances from the `Authentication` object is also fine but will not scale to large numbers of `Customer` objects. If a user can access 5,000 `Customer` objects (unlikely in this case, but imagine if it were a popular vet for a large Pony Club!) the amount of memory consumed and the time required to construct the `Authentication` object would be undesirable. The final method, opening the `Customer` directly from external code, is probably the best of the three. -It achieves separation of concerns and does not misuse memory or CPU cycles, but it is still inefficient in that both the `AccessDecisionVoter` and the eventual business method itself perform a call to the DAO responsible for retrieving the `Customer` object. +It achieves separation of concerns and does not misuse memory or CPU cycles, but it is still inefficient in that both the `AuthorizationManager` and the eventual business method itself perform a call to the DAO responsible for retrieving the `Customer` object. Two accesses per method invocation is clearly undesirable. In addition, with every approach listed, you need to write your own access control list (ACL) persistence and business logic from scratch. @@ -40,6 +40,11 @@ Fortunately, there is another alternative, which we discuss later. Spring Security's ACL services are shipped in the `spring-security-acl-xxx.jar`. You need to add this JAR to your classpath to use Spring Security's domain object instance security capabilities. +[NOTE] +==== +If you need access to the legacy Access API that includes `AclEntryVoter`, please also include `spring-security-access-xxx.jar`. +==== + Spring Security's domain object instance security capabilities center on the concept of an access control list (ACL). Every domain object instance in your system has its own ACL, and the ACL records details of who can and cannot work with that domain object. With this in mind, Spring Security provides three main ACL-related capabilities to your application: diff --git a/docs/modules/ROOT/pages/servlet/authorization/architecture.adoc b/docs/modules/ROOT/pages/servlet/authorization/architecture.adoc index cdf8b7ee09..ee6bf7dd63 100644 --- a/docs/modules/ROOT/pages/servlet/authorization/architecture.adoc +++ b/docs/modules/ROOT/pages/servlet/authorization/architecture.adoc @@ -10,7 +10,7 @@ This section describes the Spring Security architecture that applies to authoriz == Authorities xref:servlet/authentication/architecture.adoc#servlet-authentication-authentication[`Authentication`] discusses how all `Authentication` implementations store a list of `GrantedAuthority` objects. These represent the authorities that have been granted to the principal. -The `GrantedAuthority` objects are inserted into the `Authentication` object by the `AuthenticationManager` and are later read by `AccessDecisionManager` instances when making authorization decisions. +The `GrantedAuthority` objects are inserted into the `Authentication` object by the `AuthenticationManager` and are later read by `AuthorizationManager` instances when making authorization decisions. The `GrantedAuthority` interface has only one method: @@ -347,6 +347,28 @@ Spring Security contains some legacy components. Since they are not yet removed, documentation is included for historical purposes. Their recommended replacements are above. +When accessing legacy authorization components, please also include the `spring-security-access` dependency like so: + +[tabs] +====== +Maven:: ++ +[source,xml,role="primary"] +---- + + org.springframework.security + spring-security-access + +---- + +Gradle:: ++ +[source,groovy,role="primary"] +---- +implementation('org.springframework.security:spring-security-access') +---- +====== + [[authz-access-decision-manager]] === The AccessDecisionManager The `AccessDecisionManager` is called by the `AbstractSecurityInterceptor` and is responsible for making final access control decisions. diff --git a/docs/modules/ROOT/pages/servlet/authorization/index.adoc b/docs/modules/ROOT/pages/servlet/authorization/index.adoc index f38085253f..1b6678af03 100644 --- a/docs/modules/ROOT/pages/servlet/authorization/index.adoc +++ b/docs/modules/ROOT/pages/servlet/authorization/index.adoc @@ -11,4 +11,11 @@ You should consider attaching authorization rules to xref:servlet/authorization/ In either case, you can listen and react to xref:servlet/authorization/events.adoc[authorization events] that each authorization check publishes. Below there is also wealth of detail about xref:servlet/authorization/architecture.adoc[how Spring Security authorization works] and how, having established a basic model, it can be fine-tuned. +[NOTE] +==== +As of Spring Security 7, the Access API (`AccessDecisionManager`, `AccessDecisionVoter`, etc.) are moved to a legacy module, `spring-security-access`. +For new applications, there is no need to include the dependency. +For older applications that have not yet migrated to the Authorization API, this module is available to assist your continued migration efforts. +==== + diff --git a/docs/modules/ROOT/pages/servlet/authorization/method-security.adoc b/docs/modules/ROOT/pages/servlet/authorization/method-security.adoc index 15e3da45cc..181c9bfc18 100644 --- a/docs/modules/ROOT/pages/servlet/authorization/method-security.adoc +++ b/docs/modules/ROOT/pages/servlet/authorization/method-security.adoc @@ -3089,6 +3089,28 @@ Make sure to read the <> section for If you are using `@EnableGlobalMethodSecurity`, you should migrate to `@EnableMethodSecurity`. +If you cannot migrate at this time, please include the `spring-security-access` module as a dependency like so: + +[tabs] +====== +Maven:: ++ +[source,xml,role="primary"] +---- + + org.springframework.security + spring-security-access + +---- + +Gradle:: ++ +[source,groovy,role="primary"] +---- +implementation('org.springframework.security:spring-security-access') +---- +====== + [[servlet-replace-globalmethodsecurity-with-methodsecurity]] === Replace xref:servlet/authorization/method-security.adoc#jc-enable-global-method-security[global method security] with xref:servlet/authorization/method-security.adoc#jc-enable-method-security[method security] diff --git a/docs/modules/ROOT/pages/whats-new.adoc b/docs/modules/ROOT/pages/whats-new.adoc index c09c26b019..48c78165b7 100644 --- a/docs/modules/ROOT/pages/whats-new.adoc +++ b/docs/modules/ROOT/pages/whats-new.adoc @@ -14,6 +14,7 @@ Each section that follows will indicate the more notable removals as well as the * Removed `AuthorizationManager#check` in favor of `AuthorizationManager#authorize` * Added xref:servlet/authorization/architecture.adoc#authz-authorization-manager-factory[`AuthorizationManagerFactory`] for creating `AuthorizationManager` instances in xref:servlet/authorization/authorize-http-requests.adoc#customizing-authorization-managers[request-based] and xref:servlet/authorization/method-security.adoc#customizing-authorization-managers[method-based] authorization components * Added `Authentication.Builder` for mutating and merging `Authentication` instances +* Moved Access API (`AccessDecisionManager`, `AccessDecisionVoter`, etc.) to a new module, `spring-security-access` == Config