diff --git a/config/spring-security-config.gradle b/config/spring-security-config.gradle index 5e59021cc7..9e603d5bab 100644 --- a/config/spring-security-config.gradle +++ b/config/spring-security-config.gradle @@ -38,7 +38,6 @@ dependencies { optional'org.springframework:spring-websocket' optional 'org.jetbrains.kotlin:kotlin-reflect' optional 'org.jetbrains.kotlin:kotlin-stdlib-jdk8' - optional 'javax.annotation:jsr250-api' provided 'javax.servlet:javax.servlet-api' diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/EnableMethodSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/EnableMethodSecurity.java deleted file mode 100644 index c64a4355be..0000000000 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/EnableMethodSecurity.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2002-2021 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.config.annotation.method.configuration; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.springframework.context.annotation.AdviceMode; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.core.Ordered; -import org.springframework.security.access.annotation.Secured; - -/** - * Enables Spring Security Method Security. - * @author Evgeniy Cheban - * @since 5.5 - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -@Documented -@Import(MethodSecuritySelector.class) -@Configuration -public @interface EnableMethodSecurity { - - /** - * Determines if Spring Security's {@link Secured} annotation should be enabled. - * Default is false. - * @return true if {@link Secured} annotation should be enabled false otherwise - */ - boolean securedEnabled() default false; - - /** - * Determines if JSR-250 annotations should be enabled. Default is false. - * @return true if JSR-250 should be enabled false otherwise - */ - boolean jsr250Enabled() default false; - - /** - * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed to - * standard Java interface-based proxies. The default is {@code false}. - * Applicable only if {@link #mode()} is set to {@link AdviceMode#PROXY}. - *

- * Note that setting this attribute to {@code true} will affect all - * Spring-managed beans requiring proxying, not just those marked with - * {@code @Cacheable}. For example, other beans marked with Spring's - * {@code @Transactional} annotation will be upgraded to subclass proxying at the same - * time. This approach has no negative impact in practice unless one is explicitly - * expecting one type of proxy vs another, e.g. in tests. - * @return true if subclass-based (CGLIB) proxies are to be created - */ - boolean proxyTargetClass() default false; - - /** - * Indicate how security advice should be applied. The default is - * {@link AdviceMode#PROXY}. - * @see AdviceMode - * @return the {@link AdviceMode} to use - */ - AdviceMode mode() default AdviceMode.PROXY; - - /** - * Indicate the ordering of the execution of the security advisor when multiple - * advices are applied at a specific joinpoint. The default is - * {@link Ordered#LOWEST_PRECEDENCE}. - * @return the order the security advisor should be applied - */ - int order() default Ordered.LOWEST_PRECEDENCE; - -} diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityConfiguration.java deleted file mode 100644 index d9af0aa132..0000000000 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityConfiguration.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright 2002-2021 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.config.annotation.method.configuration; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import org.springframework.aop.support.DefaultPointcutAdvisor; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.ImportAware; -import org.springframework.context.annotation.Role; -import org.springframework.core.annotation.AnnotationAttributes; -import org.springframework.core.type.AnnotationMetadata; -import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; -import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; -import org.springframework.security.authorization.method.AuthorizationMethodInterceptor; -import org.springframework.security.authorization.method.AuthorizationMethodInterceptors; -import org.springframework.security.authorization.method.DelegatingAuthorizationMethodInterceptor; -import org.springframework.security.authorization.method.Jsr250AuthorizationManager; -import org.springframework.security.authorization.method.PostAuthorizeAuthorizationManager; -import org.springframework.security.authorization.method.PostFilterAuthorizationMethodInterceptor; -import org.springframework.security.authorization.method.PreAuthorizeAuthorizationManager; -import org.springframework.security.authorization.method.PreFilterAuthorizationMethodInterceptor; -import org.springframework.security.authorization.method.SecuredAuthorizationManager; -import org.springframework.security.config.core.GrantedAuthorityDefaults; -import org.springframework.util.Assert; - -/** - * Base {@link Configuration} for enabling Spring Security Method Security. - * - * @author Evgeniy Cheban - * @author Josh Cummings - * @see EnableMethodSecurity - * @since 5.5 - */ -@Configuration(proxyBeanMethods = false) -@Role(BeanDefinition.ROLE_INFRASTRUCTURE) -final class MethodSecurityConfiguration implements ImportAware, InitializingBean { - - private MethodSecurityExpressionHandler methodSecurityExpressionHandler; - - private GrantedAuthorityDefaults grantedAuthorityDefaults; - - private AuthorizationMethodInterceptor interceptor; - - private AnnotationAttributes enableMethodSecurity; - - @Bean - @Role(BeanDefinition.ROLE_INFRASTRUCTURE) - DefaultPointcutAdvisor methodSecurityAdvisor() { - AuthorizationMethodInterceptor interceptor = getInterceptor(); - DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(interceptor.getPointcut(), interceptor); - advisor.setOrder(order()); - return advisor; - } - - private MethodSecurityExpressionHandler getMethodSecurityExpressionHandler() { - if (this.methodSecurityExpressionHandler == null) { - DefaultMethodSecurityExpressionHandler methodSecurityExpressionHandler = new DefaultMethodSecurityExpressionHandler(); - if (this.grantedAuthorityDefaults != null) { - methodSecurityExpressionHandler.setDefaultRolePrefix(this.grantedAuthorityDefaults.getRolePrefix()); - } - this.methodSecurityExpressionHandler = methodSecurityExpressionHandler; - } - return this.methodSecurityExpressionHandler; - } - - @Autowired(required = false) - void setMethodSecurityExpressionHandler(MethodSecurityExpressionHandler methodSecurityExpressionHandler) { - this.methodSecurityExpressionHandler = methodSecurityExpressionHandler; - } - - @Autowired(required = false) - void setGrantedAuthorityDefaults(GrantedAuthorityDefaults grantedAuthorityDefaults) { - this.grantedAuthorityDefaults = grantedAuthorityDefaults; - } - - private AuthorizationMethodInterceptor getInterceptor() { - if (this.interceptor != null) { - return this.interceptor; - } - List interceptors = new ArrayList<>(); - interceptors.addAll(createDefaultAuthorizationMethodBeforeAdvice()); - interceptors.addAll(createDefaultAuthorizationMethodAfterAdvice()); - return new DelegatingAuthorizationMethodInterceptor(interceptors); - } - - private List createDefaultAuthorizationMethodBeforeAdvice() { - List beforeAdvices = new ArrayList<>(); - beforeAdvices.add(getPreFilterAuthorizationMethodBeforeAdvice()); - beforeAdvices.add(getPreAuthorizeAuthorizationMethodBeforeAdvice()); - if (securedEnabled()) { - beforeAdvices.add(getSecuredAuthorizationMethodBeforeAdvice()); - } - if (jsr250Enabled()) { - beforeAdvices.add(getJsr250AuthorizationMethodBeforeAdvice()); - } - return beforeAdvices; - } - - private PreFilterAuthorizationMethodInterceptor getPreFilterAuthorizationMethodBeforeAdvice() { - PreFilterAuthorizationMethodInterceptor interceptor = new PreFilterAuthorizationMethodInterceptor(); - interceptor.setExpressionHandler(getMethodSecurityExpressionHandler()); - return interceptor; - } - - private AuthorizationMethodInterceptor getPreAuthorizeAuthorizationMethodBeforeAdvice() { - PreAuthorizeAuthorizationManager authorizationManager = new PreAuthorizeAuthorizationManager(); - authorizationManager.setExpressionHandler(getMethodSecurityExpressionHandler()); - return AuthorizationMethodInterceptors.preAuthorize(authorizationManager); - } - - private AuthorizationMethodInterceptor getSecuredAuthorizationMethodBeforeAdvice() { - return AuthorizationMethodInterceptors.secured(new SecuredAuthorizationManager()); - } - - private AuthorizationMethodInterceptor getJsr250AuthorizationMethodBeforeAdvice() { - Jsr250AuthorizationManager authorizationManager = new Jsr250AuthorizationManager(); - if (this.grantedAuthorityDefaults != null) { - authorizationManager.setRolePrefix(this.grantedAuthorityDefaults.getRolePrefix()); - } - return AuthorizationMethodInterceptors.jsr250(authorizationManager); - } - - @Autowired(required = false) - void setAuthorizationMethodInterceptor(AuthorizationMethodInterceptor interceptor) { - this.interceptor = interceptor; - } - - private List createDefaultAuthorizationMethodAfterAdvice() { - List afterAdvices = new ArrayList<>(); - afterAdvices.add(getPostFilterAuthorizationMethodAfterAdvice()); - afterAdvices.add(getPostAuthorizeAuthorizationMethodAfterAdvice()); - return afterAdvices; - } - - private AuthorizationMethodInterceptor getPostFilterAuthorizationMethodAfterAdvice() { - PostFilterAuthorizationMethodInterceptor interceptor = new PostFilterAuthorizationMethodInterceptor(); - interceptor.setExpressionHandler(getMethodSecurityExpressionHandler()); - return interceptor; - } - - private AuthorizationMethodInterceptor getPostAuthorizeAuthorizationMethodAfterAdvice() { - PostAuthorizeAuthorizationManager authorizationManager = new PostAuthorizeAuthorizationManager(); - authorizationManager.setExpressionHandler(getMethodSecurityExpressionHandler()); - return AuthorizationMethodInterceptors.postAuthorize(authorizationManager); - } - - @Override - public void setImportMetadata(AnnotationMetadata importMetadata) { - Map attributes = importMetadata.getAnnotationAttributes(EnableMethodSecurity.class.getName()); - this.enableMethodSecurity = AnnotationAttributes.fromMap(attributes); - } - - @Override - public void afterPropertiesSet() throws Exception { - if (!securedEnabled() && !jsr250Enabled()) { - return; - } - Assert.isNull(this.interceptor, - "You have specified your own advice, meaning that the annotation attributes securedEnabled and jsr250Enabled will be ignored. Please choose one or the other."); - } - - private boolean securedEnabled() { - return this.enableMethodSecurity.getBoolean("securedEnabled"); - } - - private boolean jsr250Enabled() { - return this.enableMethodSecurity.getBoolean("jsr250Enabled"); - } - - private int order() { - return this.enableMethodSecurity.getNumber("order"); - } - -} diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecuritySelector.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecuritySelector.java deleted file mode 100644 index ed0df62454..0000000000 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecuritySelector.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2002-2021 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.config.annotation.method.configuration; - -import java.util.ArrayList; -import java.util.List; - -import org.springframework.context.annotation.AdviceMode; -import org.springframework.context.annotation.AdviceModeImportSelector; -import org.springframework.context.annotation.AutoProxyRegistrar; - -/** - * Dynamically determines which imports to include using the {@link EnableMethodSecurity} - * annotation. - * - * @author Evgeniy Cheban - * @since 5.5 - */ -final class MethodSecuritySelector extends AdviceModeImportSelector { - - @Override - protected String[] selectImports(AdviceMode adviceMode) { - if (adviceMode == AdviceMode.PROXY) { - return getProxyImports(); - } - throw new IllegalStateException("AdviceMode '" + adviceMode + "' is not supported"); - } - - private String[] getProxyImports() { - List result = new ArrayList<>(); - result.add(AutoProxyRegistrar.class.getName()); - result.add(MethodSecurityConfiguration.class.getName()); - return result.toArray(new String[0]); - } - -} diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityConfigurationTests.java deleted file mode 100644 index ea8c88597c..0000000000 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityConfigurationTests.java +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Copyright 2002-2021 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.config.annotation.method.configuration; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.function.Supplier; - -import org.aopalliance.intercept.MethodInvocation; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.aop.Pointcut; -import org.springframework.aop.support.JdkRegexpMethodPointcut; -import org.springframework.beans.factory.BeanCreationException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.access.PermissionEvaluator; -import org.springframework.security.access.annotation.BusinessService; -import org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl; -import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; -import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; -import org.springframework.security.authorization.AuthorizationDecision; -import org.springframework.security.authorization.AuthorizationManager; -import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor; -import org.springframework.security.authorization.method.AuthorizationMethodInterceptor; -import org.springframework.security.config.test.SpringTestRule; -import org.springframework.security.core.Authentication; -import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners; -import org.springframework.security.test.context.support.WithAnonymousUser; -import org.springframework.security.test.context.support.WithMockUser; -import org.springframework.test.context.junit4.SpringRunner; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; - -/** - * Tests for {@link MethodSecurityConfiguration}. - * - * @author Evgeniy Cheban - */ -@RunWith(SpringRunner.class) -@SecurityTestExecutionListeners -public class MethodSecurityConfigurationTests { - - @Rule - public final SpringTestRule spring = new SpringTestRule(); - - @Autowired(required = false) - MethodSecurityService methodSecurityService; - - @Autowired(required = false) - BusinessService businessService; - - @WithMockUser(roles = "ADMIN") - @Test - public void preAuthorizeWhenRoleAdminThenAccessDeniedException() { - this.spring.register(MethodSecurityServiceConfig.class).autowire(); - assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.methodSecurityService::preAuthorize) - .withMessage("Access Denied"); - } - - @WithAnonymousUser - @Test - public void preAuthorizePermitAllWhenRoleAnonymousThenPasses() { - this.spring.register(MethodSecurityServiceConfig.class).autowire(); - String result = this.methodSecurityService.preAuthorizePermitAll(); - assertThat(result).isNull(); - } - - @WithAnonymousUser - @Test - public void preAuthorizeNotAnonymousWhenRoleAnonymousThenAccessDeniedException() { - this.spring.register(MethodSecurityServiceConfig.class).autowire(); - assertThatExceptionOfType(AccessDeniedException.class) - .isThrownBy(this.methodSecurityService::preAuthorizeNotAnonymous).withMessage("Access Denied"); - } - - @WithMockUser - @Test - public void preAuthorizeNotAnonymousWhenRoleUserThenPasses() { - this.spring.register(MethodSecurityServiceConfig.class).autowire(); - this.methodSecurityService.preAuthorizeNotAnonymous(); - } - - @WithMockUser - @Test - public void securedWhenRoleUserThenAccessDeniedException() { - this.spring.register(MethodSecurityServiceEnabledConfig.class).autowire(); - assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.methodSecurityService::secured) - .withMessage("Access Denied"); - } - - @WithMockUser(roles = "ADMIN") - @Test - public void securedWhenRoleAdminThenPasses() { - this.spring.register(MethodSecurityServiceConfig.class).autowire(); - String result = this.methodSecurityService.secured(); - assertThat(result).isNull(); - } - - @WithMockUser(roles = "ADMIN") - @Test - public void securedUserWhenRoleAdminThenAccessDeniedException() { - this.spring.register(MethodSecurityServiceEnabledConfig.class).autowire(); - assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.methodSecurityService::securedUser) - .withMessage("Access Denied"); - } - - @WithMockUser - @Test - public void securedUserWhenRoleUserThenPasses() { - this.spring.register(MethodSecurityServiceConfig.class).autowire(); - String result = this.methodSecurityService.securedUser(); - assertThat(result).isNull(); - } - - @WithMockUser - @Test - public void preAuthorizeAdminWhenRoleUserThenAccessDeniedException() { - this.spring.register(MethodSecurityServiceConfig.class).autowire(); - assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.methodSecurityService::preAuthorizeAdmin) - .withMessage("Access Denied"); - } - - @WithMockUser(roles = "ADMIN") - @Test - public void preAuthorizeAdminWhenRoleAdminThenPasses() { - this.spring.register(MethodSecurityServiceConfig.class).autowire(); - this.methodSecurityService.preAuthorizeAdmin(); - } - - @WithMockUser - @Test - public void postHasPermissionWhenParameterIsNotGrantThenAccessDeniedException() { - this.spring.register(CustomPermissionEvaluatorConfig.class, MethodSecurityServiceConfig.class).autowire(); - assertThatExceptionOfType(AccessDeniedException.class) - .isThrownBy(() -> this.methodSecurityService.postHasPermission("deny")).withMessage("Access Denied"); - } - - @WithMockUser - @Test - public void postHasPermissionWhenParameterIsGrantThenPasses() { - this.spring.register(CustomPermissionEvaluatorConfig.class, MethodSecurityServiceConfig.class).autowire(); - String result = this.methodSecurityService.postHasPermission("grant"); - assertThat(result).isNull(); - } - - @WithMockUser - @Test - public void postAnnotationWhenParameterIsNotGrantThenAccessDeniedException() { - this.spring.register(MethodSecurityServiceConfig.class).autowire(); - assertThatExceptionOfType(AccessDeniedException.class) - .isThrownBy(() -> this.methodSecurityService.postAnnotation("deny")).withMessage("Access Denied"); - } - - @WithMockUser - @Test - public void postAnnotationWhenParameterIsGrantThenPasses() { - this.spring.register(MethodSecurityServiceConfig.class).autowire(); - String result = this.methodSecurityService.postAnnotation("grant"); - assertThat(result).isNull(); - } - - @WithMockUser("bob") - @Test - public void methodReturningAListWhenPrePostFiltersConfiguredThenFiltersList() { - this.spring.register(BusinessServiceConfig.class).autowire(); - List names = new ArrayList<>(); - names.add("bob"); - names.add("joe"); - names.add("sam"); - List result = this.businessService.methodReturningAList(names); - assertThat(result).hasSize(1); - assertThat(result.get(0)).isEqualTo("bob"); - } - - @WithMockUser("bob") - @Test - public void methodReturningAnArrayWhenPostFilterConfiguredThenFiltersArray() { - this.spring.register(BusinessServiceConfig.class).autowire(); - List names = new ArrayList<>(); - names.add("bob"); - names.add("joe"); - names.add("sam"); - Object[] result = this.businessService.methodReturningAnArray(names.toArray()); - assertThat(result).hasSize(1); - assertThat(result[0]).isEqualTo("bob"); - } - - @WithMockUser("bob") - @Test - public void securedUserWhenCustomBeforeAdviceConfiguredAndNameBobThenPasses() { - this.spring.register(CustomAuthorizationManagerBeforeAdviceConfig.class, MethodSecurityServiceConfig.class) - .autowire(); - String result = this.methodSecurityService.securedUser(); - assertThat(result).isNull(); - } - - @WithMockUser("joe") - @Test - public void securedUserWhenCustomBeforeAdviceConfiguredAndNameNotBobThenAccessDeniedException() { - this.spring.register(CustomAuthorizationManagerBeforeAdviceConfig.class, MethodSecurityServiceConfig.class) - .autowire(); - assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.methodSecurityService::securedUser) - .withMessage("Access Denied"); - } - - @WithMockUser("bob") - @Test - public void securedUserWhenCustomAfterAdviceConfiguredAndNameBobThenGranted() { - this.spring.register(CustomAuthorizationManagerAfterAdviceConfig.class, MethodSecurityServiceConfig.class) - .autowire(); - String result = this.methodSecurityService.securedUser(); - assertThat(result).isEqualTo("granted"); - } - - @WithMockUser("joe") - @Test - public void securedUserWhenCustomAfterAdviceConfiguredAndNameNotBobThenAccessDeniedException() { - this.spring.register(CustomAuthorizationManagerAfterAdviceConfig.class, MethodSecurityServiceConfig.class) - .autowire(); - assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.methodSecurityService::securedUser) - .withMessage("Access Denied for User 'joe'"); - } - - @WithMockUser(roles = "ADMIN") - @Test - public void jsr250WhenRoleAdminThenAccessDeniedException() { - this.spring.register(MethodSecurityServiceEnabledConfig.class).autowire(); - assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.methodSecurityService::jsr250) - .withMessage("Access Denied"); - } - - @WithAnonymousUser - @Test - public void jsr250PermitAllWhenRoleAnonymousThenPasses() { - this.spring.register(MethodSecurityServiceEnabledConfig.class).autowire(); - String result = this.methodSecurityService.jsr250PermitAll(); - assertThat(result).isNull(); - } - - @WithMockUser(roles = "ADMIN") - @Test - public void rolesAllowedUserWhenRoleAdminThenAccessDeniedException() { - this.spring.register(BusinessServiceConfig.class).autowire(); - assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.businessService::rolesAllowedUser) - .withMessage("Access Denied"); - } - - @WithMockUser - @Test - public void rolesAllowedUserWhenRoleUserThenPasses() { - this.spring.register(BusinessServiceConfig.class).autowire(); - this.businessService.rolesAllowedUser(); - } - - @WithMockUser(roles = { "ADMIN", "USER" }) - @Test - public void manyAnnotationsWhenMeetsConditionsThenReturnsFilteredList() throws Exception { - List names = Arrays.asList("harold", "jonathan", "pete", "bo"); - this.spring.register(MethodSecurityServiceEnabledConfig.class).autowire(); - List filtered = this.methodSecurityService.manyAnnotations(new ArrayList<>(names)); - assertThat(filtered).hasSize(2); - assertThat(filtered).containsExactly("harold", "jonathan"); - } - - @WithMockUser - @Test - public void manyAnnotationsWhenUserThenFails() { - List names = Arrays.asList("harold", "jonathan", "pete", "bo"); - this.spring.register(MethodSecurityServiceEnabledConfig.class).autowire(); - assertThatExceptionOfType(AccessDeniedException.class) - .isThrownBy(() -> this.methodSecurityService.manyAnnotations(new ArrayList<>(names))); - } - - @WithMockUser - @Test - public void manyAnnotationsWhenShortListThenFails() { - List names = Arrays.asList("harold", "jonathan", "pete"); - this.spring.register(MethodSecurityServiceEnabledConfig.class).autowire(); - assertThatExceptionOfType(AccessDeniedException.class) - .isThrownBy(() -> this.methodSecurityService.manyAnnotations(new ArrayList<>(names))); - } - - @WithMockUser(roles = "ADMIN") - @Test - public void manyAnnotationsWhenAdminThenFails() { - List names = Arrays.asList("harold", "jonathan", "pete", "bo"); - this.spring.register(MethodSecurityServiceEnabledConfig.class).autowire(); - assertThatExceptionOfType(AccessDeniedException.class) - .isThrownBy(() -> this.methodSecurityService.manyAnnotations(new ArrayList<>(names))); - } - - @Test - public void configureWhenCustomAdviceAndSecureEnabledThenException() { - assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() -> this.spring - .register(CustomAuthorizationManagerBeforeAdviceConfig.class, MethodSecurityServiceEnabledConfig.class) - .autowire()); - } - - @EnableMethodSecurity - static class MethodSecurityServiceConfig { - - @Bean - MethodSecurityService methodSecurityService() { - return new MethodSecurityServiceImpl(); - } - - } - - @EnableMethodSecurity(jsr250Enabled = true) - static class BusinessServiceConfig { - - @Bean - BusinessService businessService() { - return new ExpressionProtectedBusinessServiceImpl(); - } - - } - - @EnableMethodSecurity(securedEnabled = true, jsr250Enabled = true) - static class MethodSecurityServiceEnabledConfig { - - @Bean - MethodSecurityService methodSecurityService() { - return new MethodSecurityServiceImpl(); - } - - } - - @EnableMethodSecurity - static class CustomPermissionEvaluatorConfig { - - @Bean - MethodSecurityExpressionHandler methodSecurityExpressionHandler() { - DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler(); - expressionHandler.setPermissionEvaluator(new PermissionEvaluator() { - @Override - public boolean hasPermission(Authentication authentication, Object targetDomainObject, - Object permission) { - return "grant".equals(targetDomainObject); - } - - @Override - public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, - Object permission) { - throw new UnsupportedOperationException(); - } - }); - return expressionHandler; - } - - } - - @EnableMethodSecurity - static class CustomAuthorizationManagerBeforeAdviceConfig { - - @Bean - AuthorizationMethodInterceptor customBeforeAdvice() { - JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut(); - pointcut.setPattern(".*MethodSecurityServiceImpl.*securedUser"); - AuthorizationManager authorizationManager = (a, - o) -> new AuthorizationDecision("bob".equals(a.get().getName())); - return new AuthorizationManagerBeforeMethodInterceptor(pointcut, authorizationManager); - } - - } - - @EnableMethodSecurity - static class CustomAuthorizationManagerAfterAdviceConfig { - - @Bean - - AuthorizationMethodInterceptor customAfterAdvice() { - JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut(); - pointcut.setPattern(".*MethodSecurityServiceImpl.*securedUser"); - AuthorizationMethodInterceptor interceptor = new AuthorizationMethodInterceptor() { - @Override - public Pointcut getPointcut() { - return pointcut; - } - - @Override - public Object invoke(Supplier authentication, MethodInvocation mi) { - Authentication auth = authentication.get(); - if ("bob".equals(auth.getName())) { - return "granted"; - } - throw new AccessDeniedException("Access Denied for User '" + auth.getName() + "'"); - } - }; - return interceptor; - } - - } - -} diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityService.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityService.java index 4aab407ea2..525ce2a477 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityService.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityService.java @@ -16,16 +16,12 @@ package org.springframework.security.config.annotation.method.configuration; -import java.util.List; - import javax.annotation.security.DenyAll; import javax.annotation.security.PermitAll; import org.springframework.security.access.annotation.Secured; import org.springframework.security.access.prepost.PostAuthorize; -import org.springframework.security.access.prepost.PostFilter; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.access.prepost.PreFilter; import org.springframework.security.core.Authentication; import org.springframework.security.core.parameters.P; @@ -73,11 +69,4 @@ public interface MethodSecurityService { @PostAuthorize("#o?.contains('grant')") String postAnnotation(@P("o") String object); - @PreFilter("filterObject.length > 3") - @PreAuthorize("hasRole('ADMIN')") - @Secured("ROLE_USER") - @PostFilter("filterObject.length > 5") - @PostAuthorize("returnObject.size > 1") - List manyAnnotations(List array); - } diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityServiceImpl.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityServiceImpl.java index 6bf562cfeb..94a05216bc 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityServiceImpl.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityServiceImpl.java @@ -16,8 +16,6 @@ package org.springframework.security.config.annotation.method.configuration; -import java.util.List; - import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; @@ -88,9 +86,4 @@ public class MethodSecurityServiceImpl implements MethodSecurityService { return null; } - @Override - public List manyAnnotations(List object) { - return object; - } - } diff --git a/core/src/main/java/org/springframework/security/authorization/AuthorityAuthorizationManager.java b/core/src/main/java/org/springframework/security/authorization/AuthorityAuthorizationManager.java index 7d245aed6e..ea6f3d8027 100644 --- a/core/src/main/java/org/springframework/security/authorization/AuthorityAuthorizationManager.java +++ b/core/src/main/java/org/springframework/security/authorization/AuthorityAuthorizationManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2020 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. @@ -75,22 +75,9 @@ public final class AuthorityAuthorizationManager implements AuthorizationMana * @return the new instance */ public static AuthorityAuthorizationManager hasAnyRole(String... roles) { - return hasAnyRole(ROLE_PREFIX, roles); - } - - /** - * Creates an instance of {@link AuthorityAuthorizationManager} with the provided - * authorities. - * @param rolePrefix the role prefix for roles - * @param roles the authorities to check for prefixed with rolePrefix - * @param the type of object being authorized - * @return the new instance - */ - public static AuthorityAuthorizationManager hasAnyRole(String rolePrefix, String[] roles) { - Assert.notNull(rolePrefix, "rolePrefix cannot be null"); Assert.notEmpty(roles, "roles cannot be empty"); Assert.noNullElements(roles, "roles cannot contain null values"); - return hasAnyAuthority(toNamedRolesArray(rolePrefix, roles)); + return hasAnyAuthority(toNamedRolesArray(roles)); } /** @@ -106,10 +93,10 @@ public final class AuthorityAuthorizationManager implements AuthorizationMana return new AuthorityAuthorizationManager<>(authorities); } - private static String[] toNamedRolesArray(String rolePrefix, String[] roles) { + private static String[] toNamedRolesArray(String... roles) { String[] result = new String[roles.length]; for (int i = 0; i < roles.length; i++) { - result[i] = rolePrefix + roles[i]; + result[i] = ROLE_PREFIX + roles[i]; } return result; } diff --git a/core/src/main/java/org/springframework/security/authorization/method/AbstractAuthorizationManagerRegistry.java b/core/src/main/java/org/springframework/security/authorization/method/AbstractAuthorizationManagerRegistry.java deleted file mode 100644 index 47dad9dee3..0000000000 --- a/core/src/main/java/org/springframework/security/authorization/method/AbstractAuthorizationManagerRegistry.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2002-2021 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.Method; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.aopalliance.intercept.MethodInvocation; - -import org.springframework.core.MethodClassKey; -import org.springframework.lang.NonNull; -import org.springframework.security.authorization.AuthorizationManager; - -/** - * For internal use only, as this contract is likely to change - * - * @author Evgeniy Cheban - */ -abstract class AbstractAuthorizationManagerRegistry { - - static final AuthorizationManager NULL_MANAGER = (a, o) -> null; - - private final Map> cachedManagers = new ConcurrentHashMap<>(); - - /** - * Returns an {@link AuthorizationManager} for the - * {@link AuthorizationMethodInvocation}. - * @param methodInvocation the {@link AuthorizationMethodInvocation} to use - * @return an {@link AuthorizationManager} to use - */ - final AuthorizationManager getManager(AuthorizationMethodInvocation methodInvocation) { - Method method = methodInvocation.getMethod(); - Class targetClass = methodInvocation.getTargetClass(); - MethodClassKey cacheKey = new MethodClassKey(method, targetClass); - return this.cachedManagers.computeIfAbsent(cacheKey, (k) -> resolveManager(method, targetClass)); - } - - /** - * Subclasses should implement this method to provide the non-null - * {@link AuthorizationManager} for the method and the target class. - * @param method the method - * @param targetClass the target class - * @return the non-null {@link AuthorizationManager} - */ - @NonNull - abstract AuthorizationManager resolveManager(Method method, Class targetClass); - -} diff --git a/core/src/main/java/org/springframework/security/authorization/method/AbstractExpressionAttributeRegistry.java b/core/src/main/java/org/springframework/security/authorization/method/AbstractExpressionAttributeRegistry.java deleted file mode 100644 index 0dd24407ac..0000000000 --- a/core/src/main/java/org/springframework/security/authorization/method/AbstractExpressionAttributeRegistry.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2002-2021 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.Method; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.springframework.core.MethodClassKey; -import org.springframework.lang.NonNull; - -/** - * For internal use only, as this contract is likely to change - * - * @author Evgeniy Cheban - */ -abstract class AbstractExpressionAttributeRegistry { - - private final Map cachedAttributes = new ConcurrentHashMap<>(); - - /** - * Returns an {@link ExpressionAttribute} for the - * {@link AuthorizationMethodInvocation}. - * @param mi the {@link AuthorizationMethodInvocation} to use - * @return the {@link ExpressionAttribute} to use - */ - final T getAttribute(AuthorizationMethodInvocation mi) { - Method method = mi.getMethod(); - Class targetClass = mi.getTargetClass(); - return getAttribute(method, targetClass); - } - - /** - * Returns an {@link ExpressionAttribute} for the method and the target class. - * @param method the method - * @param targetClass the target class - * @return the {@link ExpressionAttribute} to use - */ - final T getAttribute(Method method, Class targetClass) { - MethodClassKey cacheKey = new MethodClassKey(method, targetClass); - return this.cachedAttributes.computeIfAbsent(cacheKey, (k) -> resolveAttribute(method, targetClass)); - } - - /** - * Subclasses should implement this method to provide the non-null - * {@link ExpressionAttribute} for the method and the target class. - * @param method the method - * @param targetClass the target class - * @return the non-null {@link ExpressionAttribute} - */ - @NonNull - abstract T resolveAttribute(Method method, Class targetClass); - -} diff --git a/core/src/main/java/org/springframework/security/authorization/method/AfterMethodAuthorizationManager.java b/core/src/main/java/org/springframework/security/authorization/method/AfterMethodAuthorizationManager.java deleted file mode 100644 index 435f05c91f..0000000000 --- a/core/src/main/java/org/springframework/security/authorization/method/AfterMethodAuthorizationManager.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2002-2021 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.util.function.Supplier; - -import org.aopalliance.intercept.MethodInvocation; - -import org.springframework.lang.Nullable; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.authorization.AuthorizationDecision; -import org.springframework.security.core.Authentication; - -/** - * An Authorization manager which can determine if an {@link Authentication} has access to - * a specific object and associated return object. Intended for use specifically to - * evaluate the returning state of a method invocation. - * - * @param the type of object that the authorization check is being done one. - * @author Josh Cummings - * @author Evgeniy Cheban - * @since 5.5 - */ -public interface AfterMethodAuthorizationManager { - - /** - * Determine if access should be granted for a specific authentication, object and - * returnedObject. - * @param authentication the {@link Supplier} of the {@link Authentication} to check - * @param object the {@code T} object to check, typically a {@link MethodInvocation} - * @param returnedObject the returnedObject from the method invocation to check - * @throws AccessDeniedException if access is not granted - */ - default void verify(Supplier authentication, T object, Object returnedObject) { - AuthorizationDecision decision = check(authentication, object, returnedObject); - if (decision != null && !decision.isGranted()) { - throw new AccessDeniedException("Access Denied"); - } - } - - /** - * Determine if access is granted for a specific authentication, object, and - * returnedObject. - * @param authentication the {@link Supplier} of the {@link Authentication} to check - * @param object the {@code T} object to check, typically a {@link MethodInvocation} - * @param returnedObject the returned object from the method invocation to check - * @return an {@link AuthorizationDecision} or null if no decision could be made - */ - @Nullable - AuthorizationDecision check(Supplier authentication, T object, Object returnedObject); - -} diff --git a/core/src/main/java/org/springframework/security/authorization/method/AfterMethodAuthorizationManagerAdapter.java b/core/src/main/java/org/springframework/security/authorization/method/AfterMethodAuthorizationManagerAdapter.java deleted file mode 100644 index 00df11da6f..0000000000 --- a/core/src/main/java/org/springframework/security/authorization/method/AfterMethodAuthorizationManagerAdapter.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2002-2021 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.util.function.Supplier; - -import org.aopalliance.intercept.MethodInvocation; - -import org.springframework.security.authorization.AuthorizationDecision; -import org.springframework.security.authorization.AuthorizationManager; -import org.springframework.security.core.Authentication; - -/** - * Adapts an {@link AuthorizationManager} into an {@link AfterMethodAuthorizationManager} - * - * @param the {@code T} object to authorize, typically a {@link MethodInvocation} - * @author Josh Cummings - * @since 5.5 - */ -public final class AfterMethodAuthorizationManagerAdapter implements AfterMethodAuthorizationManager { - - private final AuthorizationManager authorizationManager; - - /** - * Construct a {@link AfterMethodAuthorizationManagerAdapter} with the provided - * parameters - * @param authorizationManager the {@link AuthorizationManager} to adapt - */ - public AfterMethodAuthorizationManagerAdapter(AuthorizationManager authorizationManager) { - this.authorizationManager = authorizationManager; - } - - /** - * Determine if access is granted for a specific authentication and {@code T} object. - * - * Note that the {@code returnedObject} parameter is ignored - * @param authentication the {@link Supplier} of the {@link Authentication} to check - * @param object the {@code T} object to check, typically a {@link MethodInvocation} - * @param returnedObject the returned object from the method invocation, ignored in - * this implementation - * @return an {@link AuthorizationDecision} or null if no decision could be made - */ - @Override - public AuthorizationDecision check(Supplier authentication, T object, Object returnedObject) { - return this.authorizationManager.check(authentication, object); - } - -} diff --git a/core/src/main/java/org/springframework/security/authorization/method/AuthorizationManagerAfterMethodInterceptor.java b/core/src/main/java/org/springframework/security/authorization/method/AuthorizationManagerAfterMethodInterceptor.java deleted file mode 100644 index 14861ca141..0000000000 --- a/core/src/main/java/org/springframework/security/authorization/method/AuthorizationManagerAfterMethodInterceptor.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2002-2021 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.util.function.Supplier; - -import org.aopalliance.intercept.MethodInvocation; - -import org.springframework.aop.Pointcut; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.authorization.AuthorizationManager; -import org.springframework.security.core.Authentication; -import org.springframework.util.Assert; - -/** - * An {@link AuthorizationMethodInterceptor} which can determine if an - * {@link Authentication} has access to the result of an {@link MethodInvocation} using an - * {@link AuthorizationManager} - * - * @author Evgeniy Cheban - * @author Josh Cummings - * @since 5.5 - */ -public final class AuthorizationManagerAfterMethodInterceptor implements AuthorizationMethodInterceptor { - - private final Pointcut pointcut; - - private final AfterMethodAuthorizationManager authorizationManager; - - /** - * Creates an instance. - * @param pointcut the {@link Pointcut} to use - * @param authorizationManager the {@link AuthorizationManager} to use - */ - public AuthorizationManagerAfterMethodInterceptor(Pointcut pointcut, - AfterMethodAuthorizationManager authorizationManager) { - Assert.notNull(pointcut, "pointcut cannot be null"); - Assert.notNull(authorizationManager, "authorizationManager cannot be null"); - this.pointcut = pointcut; - this.authorizationManager = authorizationManager; - } - - /** - * Determine if an {@link Authentication} has access to the {@link MethodInvocation} - * using the {@link AuthorizationManager}. - * @param authentication the {@link Supplier} of the {@link Authentication} to check - * @param mi the {@link MethodInvocation} to check - * @throws AccessDeniedException if access is not granted - */ - @Override - public Object invoke(Supplier authentication, MethodInvocation mi) throws Throwable { - Object result = mi.proceed(); - this.authorizationManager.verify(authentication, mi, result); - return result; - } - - /** - * {@inheritDoc} - */ - @Override - public Pointcut getPointcut() { - return this.pointcut; - } - -} diff --git a/core/src/main/java/org/springframework/security/authorization/method/AuthorizationManagerBeforeMethodInterceptor.java b/core/src/main/java/org/springframework/security/authorization/method/AuthorizationManagerBeforeMethodInterceptor.java deleted file mode 100644 index 05a25a3b58..0000000000 --- a/core/src/main/java/org/springframework/security/authorization/method/AuthorizationManagerBeforeMethodInterceptor.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2002-2021 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.util.function.Supplier; - -import org.aopalliance.intercept.MethodInvocation; - -import org.springframework.aop.Pointcut; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.authorization.AuthorizationManager; -import org.springframework.security.core.Authentication; -import org.springframework.util.Assert; - -/** - * An {@link AuthorizationMethodInterceptor} which uses a {@link AuthorizationManager} to - * determine if an {@link Authentication} may invoke the given {@link MethodInvocation} - * - * @author Evgeniy Cheban - * @author Josh Cummings - * @since 5.5 - */ -public final class AuthorizationManagerBeforeMethodInterceptor implements AuthorizationMethodInterceptor { - - private final Pointcut pointcut; - - private final AuthorizationManager authorizationManager; - - /** - * Creates an instance. - * @param pointcut the {@link Pointcut} to use - * @param authorizationManager the {@link AuthorizationManager} to use - */ - public AuthorizationManagerBeforeMethodInterceptor(Pointcut pointcut, - AuthorizationManager authorizationManager) { - Assert.notNull(pointcut, "pointcut cannot be null"); - Assert.notNull(authorizationManager, "authorizationManager cannot be null"); - this.pointcut = pointcut; - this.authorizationManager = authorizationManager; - } - - /** - * Determine if an {@link Authentication} has access to the {@link MethodInvocation} - * using the configured {@link AuthorizationManager}. - * @param authentication the {@link Supplier} of the {@link Authentication} to check - * @param mi the {@link MethodInvocation} to check - * @throws AccessDeniedException if access is not granted - */ - @Override - public Object invoke(Supplier authentication, MethodInvocation mi) throws Throwable { - this.authorizationManager.verify(authentication, mi); - return mi.proceed(); - } - - /** - * {@inheritDoc} - */ - @Override - public Pointcut getPointcut() { - return this.pointcut; - } - -} diff --git a/core/src/main/java/org/springframework/security/authorization/method/AuthorizationMethodInterceptor.java b/core/src/main/java/org/springframework/security/authorization/method/AuthorizationMethodInterceptor.java deleted file mode 100644 index ac52e1b72c..0000000000 --- a/core/src/main/java/org/springframework/security/authorization/method/AuthorizationMethodInterceptor.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2002-2021 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.util.function.Supplier; - -import org.aopalliance.aop.Advice; -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; - -import org.springframework.aop.PointcutAdvisor; -import org.springframework.aop.framework.AopInfrastructureBean; -import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; - -/** - * A {@link MethodInterceptor} which can determine if an {@link Authentication} has access - * to the {@link MethodInvocation}. {@link #getPointcut()} describes when the interceptor - * applies. - * - * @author Evgeniy Cheban - * @author Josh Cummings - * @since 5.5 - */ -public interface AuthorizationMethodInterceptor extends MethodInterceptor, PointcutAdvisor, AopInfrastructureBean { - - /** - * {@inheritDoc} - */ - @Override - default Advice getAdvice() { - return this; - } - - /** - * {@inheritDoc} - */ - @Override - default boolean isPerInstance() { - return true; - } - - /** - * Determine if an {@link Authentication} has access to the {@link MethodInvocation} - * @param mi the {@link MethodInvocation} to intercept and potentially invoke - * @return the result of the method invocation - * @throws Throwable if the interceptor or the target object throws an exception - */ - default Object invoke(MethodInvocation mi) throws Throwable { - Supplier supplier = () -> { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if (authentication == null) { - throw new AuthenticationCredentialsNotFoundException( - "An Authentication object was not found in the SecurityContext"); - } - return authentication; - }; - return invoke(supplier, new AuthorizationMethodInvocation(supplier, mi)); - } - - /** - * Determine if an {@link Authentication} has access to the {@link MethodInvocation} - * @param authentication the {@link Supplier} of the {@link Authentication} to check - * @param mi the {@link MethodInvocation} to intercept and potentially invoke - * @return the result of the method invocation - * @throws Throwable if the interceptor or the target object throws an exception - */ - Object invoke(Supplier authentication, MethodInvocation mi) throws Throwable; - -} diff --git a/core/src/main/java/org/springframework/security/authorization/method/AuthorizationMethodInterceptors.java b/core/src/main/java/org/springframework/security/authorization/method/AuthorizationMethodInterceptors.java deleted file mode 100644 index 1d963ff7bc..0000000000 --- a/core/src/main/java/org/springframework/security/authorization/method/AuthorizationMethodInterceptors.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2002-2021 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 javax.annotation.security.DenyAll; -import javax.annotation.security.PermitAll; -import javax.annotation.security.RolesAllowed; - -import org.springframework.security.access.annotation.Secured; -import org.springframework.security.access.prepost.PostAuthorize; -import org.springframework.security.access.prepost.PreAuthorize; - -/** - * A static factory for constructing common {@link AuthorizationMethodInterceptor}s - * - * @author Josh Cummings - * @since 5.5 - * @see PreAuthorizeAuthorizationManager - * @see PostAuthorizeAuthorizationManager - * @see SecuredAuthorizationManager - * @see Jsr250AuthorizationManager - */ -public final class AuthorizationMethodInterceptors { - - public static AuthorizationMethodInterceptor preAuthorize() { - return preAuthorize(new PreAuthorizeAuthorizationManager()); - } - - public static AuthorizationMethodInterceptor preAuthorize(PreAuthorizeAuthorizationManager manager) { - return new AuthorizationManagerBeforeMethodInterceptor( - AuthorizationMethodPointcuts.forAnnotations(PreAuthorize.class), manager); - } - - public static AuthorizationMethodInterceptor postAuthorize() { - return postAuthorize(new PostAuthorizeAuthorizationManager()); - } - - public static AuthorizationMethodInterceptor postAuthorize(PostAuthorizeAuthorizationManager manager) { - return new AuthorizationManagerAfterMethodInterceptor( - AuthorizationMethodPointcuts.forAnnotations(PostAuthorize.class), manager); - } - - public static AuthorizationMethodInterceptor secured() { - return secured(new SecuredAuthorizationManager()); - } - - public static AuthorizationMethodInterceptor secured(SecuredAuthorizationManager manager) { - return new AuthorizationManagerBeforeMethodInterceptor( - AuthorizationMethodPointcuts.forAnnotations(Secured.class), manager); - } - - public static AuthorizationMethodInterceptor jsr250() { - return jsr250(new Jsr250AuthorizationManager()); - } - - public static AuthorizationMethodInterceptor jsr250(Jsr250AuthorizationManager manager) { - return new AuthorizationManagerBeforeMethodInterceptor( - AuthorizationMethodPointcuts.forAnnotations(DenyAll.class, PermitAll.class, RolesAllowed.class), - manager); - } - - private AuthorizationMethodInterceptors() { - - } - -} diff --git a/core/src/main/java/org/springframework/security/authorization/method/AuthorizationMethodInvocation.java b/core/src/main/java/org/springframework/security/authorization/method/AuthorizationMethodInvocation.java deleted file mode 100644 index d3976b406f..0000000000 --- a/core/src/main/java/org/springframework/security/authorization/method/AuthorizationMethodInvocation.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2002-2021 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 java.util.Collections; -import java.util.List; -import java.util.function.Supplier; - -import org.aopalliance.intercept.MethodInvocation; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.aop.Pointcut; -import org.springframework.aop.support.AopUtils; -import org.springframework.core.log.LogMessage; -import org.springframework.security.core.Authentication; - -/** - * @author Josh Cummings - */ -class AuthorizationMethodInvocation implements MethodInvocation { - - private final Log logger = LogFactory.getLog(getClass()); - - private final Supplier authentication; - - private final MethodInvocation methodInvocation; - - private final Class targetClass; - - private final List interceptors; - - private final int size; - - private int currentPosition = 0; - - AuthorizationMethodInvocation(Supplier authentication, MethodInvocation methodInvocation) { - this(authentication, methodInvocation, Collections.emptyList()); - } - - AuthorizationMethodInvocation(Supplier authentication, MethodInvocation methodInvocation, - List interceptors) { - this.authentication = authentication; - this.methodInvocation = methodInvocation; - this.interceptors = interceptors; - Object target = methodInvocation.getThis(); - this.targetClass = (target != null) ? AopUtils.getTargetClass(target) : null; - this.size = interceptors.size(); - } - - @Override - public Method getMethod() { - return this.methodInvocation.getMethod(); - } - - @Override - public Object[] getArguments() { - return this.methodInvocation.getArguments(); - } - - /** - * Return the target class. - * @return the target class - */ - Class getTargetClass() { - return this.targetClass; - } - - @Override - public Object proceed() throws Throwable { - if (this.currentPosition == this.size) { - if (this.logger.isDebugEnabled()) { - this.logger.debug(LogMessage.of(() -> "Pre-Authorized " + this.methodInvocation.getMethod())); - } - return this.methodInvocation.proceed(); - } - AuthorizationMethodInterceptor interceptor = this.interceptors.get(this.currentPosition); - this.currentPosition++; - Pointcut pointcut = interceptor.getPointcut(); - if (!pointcut.getClassFilter().matches(getTargetClass())) { - return proceed(); - } - if (!pointcut.getMethodMatcher().matches(getMethod(), getTargetClass())) { - return proceed(); - } - if (this.logger.isTraceEnabled()) { - this.logger.trace(LogMessage.format("Applying %s (%d/%d)", interceptor.getClass().getSimpleName(), - this.currentPosition, this.size)); - } - Object result = interceptor.invoke(this.authentication, this); - if (this.logger.isDebugEnabled()) { - this.logger.debug(LogMessage.of(() -> "Post-Authorized " + this.methodInvocation.getMethod())); - } - return result; - } - - @Override - public Object getThis() { - return this.methodInvocation.getThis(); - } - - @Override - public AccessibleObject getStaticPart() { - return this.methodInvocation.getStaticPart(); - } - -} diff --git a/core/src/main/java/org/springframework/security/authorization/method/AuthorizationMethodPointcuts.java b/core/src/main/java/org/springframework/security/authorization/method/AuthorizationMethodPointcuts.java deleted file mode 100644 index e764d95d83..0000000000 --- a/core/src/main/java/org/springframework/security/authorization/method/AuthorizationMethodPointcuts.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2002-2021 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.Annotation; - -import org.springframework.aop.Pointcut; -import org.springframework.aop.support.ComposablePointcut; -import org.springframework.aop.support.Pointcuts; -import org.springframework.aop.support.annotation.AnnotationMatchingPointcut; - -/** - * @author Josh Cummings - */ -final class AuthorizationMethodPointcuts { - - @SafeVarargs - static Pointcut forAnnotations(Class... annotations) { - ComposablePointcut pointcut = null; - for (Class annotation : annotations) { - if (pointcut == null) { - pointcut = new ComposablePointcut(classOrMethod(annotation)); - } - else { - pointcut.union(classOrMethod(annotation)); - } - } - return pointcut; - } - - private static Pointcut classOrMethod(Class annotation) { - return Pointcuts.union(new AnnotationMatchingPointcut(null, annotation, true), - new AnnotationMatchingPointcut(annotation, true)); - } - - private AuthorizationMethodPointcuts() { - - } - -} diff --git a/core/src/main/java/org/springframework/security/authorization/method/DelegatingAuthorizationMethodInterceptor.java b/core/src/main/java/org/springframework/security/authorization/method/DelegatingAuthorizationMethodInterceptor.java deleted file mode 100644 index e00e8a9922..0000000000 --- a/core/src/main/java/org/springframework/security/authorization/method/DelegatingAuthorizationMethodInterceptor.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2002-2021 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.util.Arrays; -import java.util.List; -import java.util.function.Supplier; - -import org.aopalliance.intercept.MethodInvocation; - -import org.springframework.aop.Pointcut; -import org.springframework.aop.support.ComposablePointcut; -import org.springframework.security.core.Authentication; - -/** - * Provides security interception of AOP Alliance based method invocations. - * - * Delegates to a collection of {@link AuthorizationMethodInterceptor}s - * - * @author Evgeniy Cheban - * @author Josh Cummings - * @since 5.5 - */ -public final class DelegatingAuthorizationMethodInterceptor implements AuthorizationMethodInterceptor { - - private final List interceptors; - - private final Pointcut pointcut; - - /** - * Creates an instance using the provided parameters - * @param interceptors the delegate {@link AuthorizationMethodInterceptor}s to use - */ - public DelegatingAuthorizationMethodInterceptor(AuthorizationMethodInterceptor... interceptors) { - this(Arrays.asList(interceptors)); - } - - /** - * Creates an instance using the provided parameters - * @param interceptors the delegate {@link AuthorizationMethodInterceptor}s to use - */ - public DelegatingAuthorizationMethodInterceptor(List interceptors) { - ComposablePointcut pointcut = null; - for (AuthorizationMethodInterceptor interceptor : interceptors) { - if (pointcut == null) { - pointcut = new ComposablePointcut(interceptor.getPointcut()); - } - else { - pointcut.union(interceptor.getPointcut()); - } - } - this.pointcut = pointcut; - this.interceptors = interceptors; - } - - /** - * Enforce security on this {@link MethodInvocation}. - * @param mi the method being invoked which requires a security decision - * @return the returned value from the {@link MethodInvocation}, possibly altered by - * the configured {@link AuthorizationMethodInterceptor}s - */ - @Override - public Object invoke(Supplier authentication, MethodInvocation mi) throws Throwable { - return new AuthorizationMethodInvocation(authentication, mi, this.interceptors).proceed(); - } - - /** - * {@inheritDoc} - */ - @Override - public Pointcut getPointcut() { - return this.pointcut; - } - -} diff --git a/core/src/main/java/org/springframework/security/authorization/method/ExpressionAttribute.java b/core/src/main/java/org/springframework/security/authorization/method/ExpressionAttribute.java deleted file mode 100644 index 80e49360e9..0000000000 --- a/core/src/main/java/org/springframework/security/authorization/method/ExpressionAttribute.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2002-2021 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 org.springframework.expression.Expression; - -/** - * An {@link Expression} attribute. - * - * @author Evgeniy Cheban - * @since 5.5 - */ -class ExpressionAttribute { - - /** - * Represents an empty attribute with null {@link Expression}. - */ - static final ExpressionAttribute NULL_ATTRIBUTE = new ExpressionAttribute(null); - - private final Expression expression; - - /** - * Creates an instance. - * @param expression the {@link Expression} to use - */ - ExpressionAttribute(Expression expression) { - this.expression = expression; - } - - /** - * Returns the {@link Expression}. - * @return the {@link Expression} to use - */ - Expression getExpression() { - return this.expression; - } - -} diff --git a/core/src/main/java/org/springframework/security/authorization/method/Jsr250AuthorizationManager.java b/core/src/main/java/org/springframework/security/authorization/method/Jsr250AuthorizationManager.java deleted file mode 100644 index c099e4d70f..0000000000 --- a/core/src/main/java/org/springframework/security/authorization/method/Jsr250AuthorizationManager.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2002-2021 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.Annotation; -import java.lang.reflect.AnnotatedElement; -import java.lang.reflect.Method; -import java.util.HashSet; -import java.util.Set; -import java.util.function.Supplier; - -import javax.annotation.security.DenyAll; -import javax.annotation.security.PermitAll; -import javax.annotation.security.RolesAllowed; - -import org.aopalliance.intercept.MethodInvocation; - -import org.springframework.aop.support.AopUtils; -import org.springframework.core.annotation.AnnotatedElementUtils; -import org.springframework.lang.NonNull; -import org.springframework.security.authorization.AuthorityAuthorizationManager; -import org.springframework.security.authorization.AuthorizationDecision; -import org.springframework.security.authorization.AuthorizationManager; -import org.springframework.security.core.Authentication; -import org.springframework.util.Assert; - -/** - * An {@link AuthorizationManager} which can determine if an {@link Authentication} may - * invoke the {@link MethodInvocation} by evaluating if the {@link Authentication} - * contains a specified authority from the JSR-250 security annotations. - * - * @author Evgeniy Cheban - * @since 5.5 - */ -public final class Jsr250AuthorizationManager implements AuthorizationManager { - - private static final Set> JSR250_ANNOTATIONS = new HashSet<>(); - - static { - JSR250_ANNOTATIONS.add(DenyAll.class); - JSR250_ANNOTATIONS.add(PermitAll.class); - JSR250_ANNOTATIONS.add(RolesAllowed.class); - } - - private final Jsr250AuthorizationManagerRegistry registry = new Jsr250AuthorizationManagerRegistry(); - - private String rolePrefix = "ROLE_"; - - /** - * Sets the role prefix. Defaults to "ROLE_". - * @param rolePrefix the role prefix to use - */ - public void setRolePrefix(String rolePrefix) { - Assert.notNull(rolePrefix, "rolePrefix cannot be null"); - this.rolePrefix = rolePrefix; - } - - /** - * Determine if an {@link Authentication} has access to a method by evaluating the - * {@link DenyAll}, {@link PermitAll}, and {@link RolesAllowed} annotations that - * {@link AuthorizationMethodInvocation} specifies. - * @param authentication the {@link Supplier} of the {@link Authentication} to check - * @param methodInvocation the {@link AuthorizationMethodInvocation} to check - * @return an {@link AuthorizationDecision} or null if the JSR-250 security - * annotations is not present - */ - @Override - public AuthorizationDecision check(Supplier authentication, MethodInvocation methodInvocation) { - AuthorizationManager delegate = this.registry - .getManager((AuthorizationMethodInvocation) methodInvocation); - return delegate.check(authentication, methodInvocation); - } - - private final class Jsr250AuthorizationManagerRegistry extends AbstractAuthorizationManagerRegistry { - - @NonNull - @Override - AuthorizationManager resolveManager(Method method, Class targetClass) { - for (Annotation annotation : findJsr250Annotations(method, targetClass)) { - if (annotation instanceof DenyAll) { - return (a, o) -> new AuthorizationDecision(false); - } - if (annotation instanceof PermitAll) { - return (a, o) -> new AuthorizationDecision(true); - } - if (annotation instanceof RolesAllowed) { - RolesAllowed rolesAllowed = (RolesAllowed) annotation; - return AuthorityAuthorizationManager.hasAnyRole(Jsr250AuthorizationManager.this.rolePrefix, - rolesAllowed.value()); - } - } - return NULL_MANAGER; - } - - private Set findJsr250Annotations(Method method, Class targetClass) { - Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass); - Set annotations = findAnnotations(specificMethod); - return (annotations.isEmpty()) ? findAnnotations(specificMethod.getDeclaringClass()) : annotations; - } - - private Set findAnnotations(AnnotatedElement annotatedElement) { - return AnnotatedElementUtils.findAllMergedAnnotations(annotatedElement, JSR250_ANNOTATIONS); - } - - } - -} diff --git a/core/src/main/java/org/springframework/security/authorization/method/PostAuthorizeAuthorizationManager.java b/core/src/main/java/org/springframework/security/authorization/method/PostAuthorizeAuthorizationManager.java deleted file mode 100644 index 9e486642b8..0000000000 --- a/core/src/main/java/org/springframework/security/authorization/method/PostAuthorizeAuthorizationManager.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2002-2021 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.Method; -import java.util.function.Supplier; - -import org.aopalliance.intercept.MethodInvocation; -import reactor.util.annotation.NonNull; - -import org.springframework.aop.support.AopUtils; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.expression.EvaluationContext; -import org.springframework.expression.Expression; -import org.springframework.security.access.expression.ExpressionUtils; -import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; -import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; -import org.springframework.security.access.prepost.PostAuthorize; -import org.springframework.security.authorization.AuthorizationDecision; -import org.springframework.security.authorization.AuthorizationManager; -import org.springframework.security.core.Authentication; -import org.springframework.util.Assert; - -/** - * An {@link AuthorizationManager} which can determine if an {@link Authentication} may - * return the result from an invoked {@link MethodInvocation} by evaluating an expression - * from the {@link PostAuthorize} annotation. - * - * @author Evgeniy Cheban - * @since 5.5 - */ -public final class PostAuthorizeAuthorizationManager implements AfterMethodAuthorizationManager { - - private final PostAuthorizeExpressionAttributeRegistry registry = new PostAuthorizeExpressionAttributeRegistry(); - - private MethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler(); - - /** - * Use this the {@link MethodSecurityExpressionHandler}. - * @param expressionHandler the {@link MethodSecurityExpressionHandler} to use - */ - public void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) { - Assert.notNull(expressionHandler, "expressionHandler cannot be null"); - this.expressionHandler = expressionHandler; - } - - /** - * Determine if an {@link Authentication} has access to the returned object by - * evaluating the {@link PostAuthorize} annotation that the - * {@link AuthorizationMethodInvocation} specifies. - * @param authentication the {@link Supplier} of the {@link Authentication} to check - * @param mi the {@link AuthorizationMethodInvocation} to check - * @param returnedObject the returned object to check - * @return an {@link AuthorizationDecision} or {@code null} if the - * {@link PostAuthorize} annotation is not present - */ - @Override - public AuthorizationDecision check(Supplier authentication, MethodInvocation mi, - Object returnedObject) { - ExpressionAttribute attribute = this.registry.getAttribute((AuthorizationMethodInvocation) mi); - if (attribute == ExpressionAttribute.NULL_ATTRIBUTE) { - return null; - } - EvaluationContext ctx = this.expressionHandler.createEvaluationContext(authentication.get(), mi); - this.expressionHandler.setReturnObject(returnedObject, ctx); - boolean granted = ExpressionUtils.evaluateAsBoolean(attribute.getExpression(), ctx); - return new AuthorizationDecision(granted); - } - - private final class PostAuthorizeExpressionAttributeRegistry - extends AbstractExpressionAttributeRegistry { - - @NonNull - @Override - ExpressionAttribute resolveAttribute(Method method, Class targetClass) { - Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass); - PostAuthorize postAuthorize = findPostAuthorizeAnnotation(specificMethod); - if (postAuthorize == null) { - return ExpressionAttribute.NULL_ATTRIBUTE; - } - Expression postAuthorizeExpression = PostAuthorizeAuthorizationManager.this.expressionHandler - .getExpressionParser().parseExpression(postAuthorize.value()); - return new ExpressionAttribute(postAuthorizeExpression); - } - - private PostAuthorize findPostAuthorizeAnnotation(Method method) { - PostAuthorize postAuthorize = AnnotationUtils.findAnnotation(method, PostAuthorize.class); - return (postAuthorize != null) ? postAuthorize - : AnnotationUtils.findAnnotation(method.getDeclaringClass(), PostAuthorize.class); - } - - } - -} diff --git a/core/src/main/java/org/springframework/security/authorization/method/PostFilterAuthorizationMethodInterceptor.java b/core/src/main/java/org/springframework/security/authorization/method/PostFilterAuthorizationMethodInterceptor.java deleted file mode 100644 index 40ec2b29f4..0000000000 --- a/core/src/main/java/org/springframework/security/authorization/method/PostFilterAuthorizationMethodInterceptor.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright 2002-2021 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.Method; -import java.util.function.Supplier; - -import org.aopalliance.intercept.MethodInvocation; - -import org.springframework.aop.Pointcut; -import org.springframework.aop.support.AopUtils; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.expression.EvaluationContext; -import org.springframework.expression.Expression; -import org.springframework.lang.NonNull; -import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; -import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; -import org.springframework.security.access.prepost.PostFilter; -import org.springframework.security.core.Authentication; -import org.springframework.util.Assert; - -/** - * An {@link AuthorizationMethodInterceptor} which filters a {@code returnedObject} from - * the {@link MethodInvocation} by evaluating an expression from the {@link PostFilter} - * annotation. - * - * @author Evgeniy Cheban - * @author Josh Cummings - * @since 5.5 - */ -public final class PostFilterAuthorizationMethodInterceptor implements AuthorizationMethodInterceptor { - - private final PostFilterExpressionAttributeRegistry registry = new PostFilterExpressionAttributeRegistry(); - - private final Pointcut pointcut; - - private MethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler(); - - /** - * Creates a {@link PostFilterAuthorizationMethodInterceptor} using the provided - * parameters - */ - public PostFilterAuthorizationMethodInterceptor() { - this.pointcut = AuthorizationMethodPointcuts.forAnnotations(PostFilter.class); - } - - /** - * Use this {@link MethodSecurityExpressionHandler}. - * @param expressionHandler the {@link MethodSecurityExpressionHandler} to use - */ - public void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) { - Assert.notNull(expressionHandler, "expressionHandler cannot be null"); - this.expressionHandler = expressionHandler; - } - - /** - * {@inheritDoc} - */ - @Override - public Pointcut getPointcut() { - return this.pointcut; - } - - /** - * Filter a {@code returnedObject} using the {@link PostFilter} annotation that the - * {@link AuthorizationMethodInvocation} specifies. - * @param authentication the {@link Supplier} of the {@link Authentication} to check - * @param mi the {@link AuthorizationMethodInvocation} to check check - * @return filtered {@code returnedObject} - */ - @Override - public Object invoke(Supplier authentication, MethodInvocation mi) throws Throwable { - Object returnedObject = mi.proceed(); - ExpressionAttribute attribute = this.registry.getAttribute((AuthorizationMethodInvocation) mi); - if (attribute == ExpressionAttribute.NULL_ATTRIBUTE) { - return returnedObject; - } - EvaluationContext ctx = this.expressionHandler.createEvaluationContext(authentication.get(), mi); - return this.expressionHandler.filter(returnedObject, attribute.getExpression(), ctx); - } - - private final class PostFilterExpressionAttributeRegistry - extends AbstractExpressionAttributeRegistry { - - @NonNull - @Override - ExpressionAttribute resolveAttribute(Method method, Class targetClass) { - Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass); - PostFilter postFilter = findPostFilterAnnotation(specificMethod); - if (postFilter == null) { - return ExpressionAttribute.NULL_ATTRIBUTE; - } - Expression postFilterExpression = PostFilterAuthorizationMethodInterceptor.this.expressionHandler - .getExpressionParser().parseExpression(postFilter.value()); - return new ExpressionAttribute(postFilterExpression); - } - - private PostFilter findPostFilterAnnotation(Method method) { - PostFilter postFilter = AnnotationUtils.findAnnotation(method, PostFilter.class); - return (postFilter != null) ? postFilter - : AnnotationUtils.findAnnotation(method.getDeclaringClass(), PostFilter.class); - } - - } - -} diff --git a/core/src/main/java/org/springframework/security/authorization/method/PreAuthorizeAuthorizationManager.java b/core/src/main/java/org/springframework/security/authorization/method/PreAuthorizeAuthorizationManager.java deleted file mode 100644 index 9f7fc77cb2..0000000000 --- a/core/src/main/java/org/springframework/security/authorization/method/PreAuthorizeAuthorizationManager.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2002-2021 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.Method; -import java.util.function.Supplier; - -import org.aopalliance.intercept.MethodInvocation; -import reactor.util.annotation.NonNull; - -import org.springframework.aop.support.AopUtils; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.expression.EvaluationContext; -import org.springframework.expression.Expression; -import org.springframework.security.access.expression.ExpressionUtils; -import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; -import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.authorization.AuthorizationDecision; -import org.springframework.security.authorization.AuthorizationManager; -import org.springframework.security.core.Authentication; -import org.springframework.util.Assert; - -/** - * An {@link AuthorizationManager} which can determine if an {@link Authentication} may - * invoke the {@link MethodInvocation} by evaluating an expression from the - * {@link PreAuthorize} annotation. - * - * @author Evgeniy Cheban - * @since 5.5 - */ -public final class PreAuthorizeAuthorizationManager implements AuthorizationManager { - - private final PreAuthorizeExpressionAttributeRegistry registry = new PreAuthorizeExpressionAttributeRegistry(); - - private MethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler(); - - /** - * Sets the {@link MethodSecurityExpressionHandler}. - * @param expressionHandler the {@link MethodSecurityExpressionHandler} to use - */ - public void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) { - Assert.notNull(expressionHandler, "expressionHandler cannot be null"); - this.expressionHandler = expressionHandler; - } - - /** - * Determine if an {@link Authentication} has access to a method by evaluating an - * expression from the {@link PreAuthorize} annotation that the - * {@link AuthorizationMethodInvocation} specifies. - * @param authentication the {@link Supplier} of the {@link Authentication} to check - * @param mi the {@link AuthorizationMethodInvocation} to check - * @return an {@link AuthorizationDecision} or {@code null} if the - * {@link PreAuthorize} annotation is not present - */ - @Override - public AuthorizationDecision check(Supplier authentication, MethodInvocation mi) { - ExpressionAttribute attribute = this.registry.getAttribute((AuthorizationMethodInvocation) mi); - if (attribute == ExpressionAttribute.NULL_ATTRIBUTE) { - return null; - } - EvaluationContext ctx = this.expressionHandler.createEvaluationContext(authentication.get(), mi); - boolean granted = ExpressionUtils.evaluateAsBoolean(attribute.getExpression(), ctx); - return new AuthorizationDecision(granted); - } - - private final class PreAuthorizeExpressionAttributeRegistry - extends AbstractExpressionAttributeRegistry { - - @NonNull - @Override - ExpressionAttribute resolveAttribute(Method method, Class targetClass) { - Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass); - PreAuthorize preAuthorize = findPreAuthorizeAnnotation(specificMethod); - if (preAuthorize == null) { - return ExpressionAttribute.NULL_ATTRIBUTE; - } - Expression preAuthorizeExpression = PreAuthorizeAuthorizationManager.this.expressionHandler - .getExpressionParser().parseExpression(preAuthorize.value()); - return new ExpressionAttribute(preAuthorizeExpression); - } - - private PreAuthorize findPreAuthorizeAnnotation(Method method) { - PreAuthorize preAuthorize = AnnotationUtils.findAnnotation(method, PreAuthorize.class); - return (preAuthorize != null) ? preAuthorize - : AnnotationUtils.findAnnotation(method.getDeclaringClass(), PreAuthorize.class); - } - - } - -} diff --git a/core/src/main/java/org/springframework/security/authorization/method/PreFilterAuthorizationMethodInterceptor.java b/core/src/main/java/org/springframework/security/authorization/method/PreFilterAuthorizationMethodInterceptor.java deleted file mode 100644 index 0e56e4d47f..0000000000 --- a/core/src/main/java/org/springframework/security/authorization/method/PreFilterAuthorizationMethodInterceptor.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2002-2021 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.Method; -import java.util.function.Supplier; - -import org.aopalliance.intercept.MethodInvocation; - -import org.springframework.aop.Pointcut; -import org.springframework.aop.support.AopUtils; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.expression.EvaluationContext; -import org.springframework.expression.Expression; -import org.springframework.lang.NonNull; -import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; -import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; -import org.springframework.security.access.prepost.PreFilter; -import org.springframework.security.core.Authentication; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * An {@link AuthorizationMethodInterceptor} which filters a method argument by evaluating - * an expression from the {@link PreFilter} annotation. - * - * @author Evgeniy Cheban - * @author Josh Cummings - * @since 5.5 - */ -public final class PreFilterAuthorizationMethodInterceptor implements AuthorizationMethodInterceptor { - - private final PreFilterExpressionAttributeRegistry registry = new PreFilterExpressionAttributeRegistry(); - - private final Pointcut pointcut; - - private MethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler(); - - /** - * Creates a {@link PreFilterAuthorizationMethodInterceptor} using the provided - * parameters - */ - public PreFilterAuthorizationMethodInterceptor() { - this.pointcut = AuthorizationMethodPointcuts.forAnnotations(PreFilter.class); - } - - /** - * Use this {@link MethodSecurityExpressionHandler} - * @param expressionHandler the {@link MethodSecurityExpressionHandler} to use - */ - public void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) { - Assert.notNull(expressionHandler, "expressionHandler cannot be null"); - this.expressionHandler = expressionHandler; - } - - /** - * {@inheritDoc} - */ - @Override - public Pointcut getPointcut() { - return this.pointcut; - } - - /** - * Filter the method argument specified in the {@link PreFilter} annotation that - * {@link AuthorizationMethodInvocation} specifies. - * @param authentication the {@link Supplier} of the {@link Authentication} to check - * @param mi the {@link AuthorizationMethodInvocation} to check - */ - @Override - public Object invoke(Supplier authentication, MethodInvocation mi) throws Throwable { - PreFilterExpressionAttribute attribute = this.registry.getAttribute((AuthorizationMethodInvocation) mi); - if (attribute == PreFilterExpressionAttribute.NULL_ATTRIBUTE) { - return mi.proceed(); - } - EvaluationContext ctx = this.expressionHandler.createEvaluationContext(authentication.get(), mi); - Object filterTarget = findFilterTarget(attribute.filterTarget, ctx, mi); - this.expressionHandler.filter(filterTarget, attribute.getExpression(), ctx); - return mi.proceed(); - } - - private Object findFilterTarget(String filterTargetName, EvaluationContext ctx, MethodInvocation methodInvocation) { - Object filterTarget; - if (StringUtils.hasText(filterTargetName)) { - filterTarget = ctx.lookupVariable(filterTargetName); - Assert.notNull(filterTarget, () -> "Filter target was null, or no argument with name '" + filterTargetName - + "' found in method."); - } - else { - Object[] arguments = methodInvocation.getArguments(); - Assert.state(arguments.length == 1, - "Unable to determine the method argument for filtering. Specify the filter target."); - filterTarget = arguments[0]; - Assert.notNull(filterTarget, - "Filter target was null. Make sure you passing the correct value in the method argument."); - } - Assert.state(!filterTarget.getClass().isArray(), - "Pre-filtering on array types is not supported. Using a Collection will solve this problem."); - return filterTarget; - } - - private final class PreFilterExpressionAttributeRegistry - extends AbstractExpressionAttributeRegistry { - - @NonNull - @Override - PreFilterExpressionAttribute resolveAttribute(Method method, Class targetClass) { - Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass); - PreFilter preFilter = findPreFilterAnnotation(specificMethod); - if (preFilter == null) { - return PreFilterExpressionAttribute.NULL_ATTRIBUTE; - } - Expression preFilterExpression = PreFilterAuthorizationMethodInterceptor.this.expressionHandler - .getExpressionParser().parseExpression(preFilter.value()); - return new PreFilterExpressionAttribute(preFilterExpression, preFilter.filterTarget()); - } - - private PreFilter findPreFilterAnnotation(Method method) { - PreFilter preFilter = AnnotationUtils.findAnnotation(method, PreFilter.class); - return (preFilter != null) ? preFilter - : AnnotationUtils.findAnnotation(method.getDeclaringClass(), PreFilter.class); - } - - } - - private static final class PreFilterExpressionAttribute extends ExpressionAttribute { - - private static final PreFilterExpressionAttribute NULL_ATTRIBUTE = new PreFilterExpressionAttribute(null, null); - - private final String filterTarget; - - private PreFilterExpressionAttribute(Expression expression, String filterTarget) { - super(expression); - this.filterTarget = filterTarget; - } - - } - -} diff --git a/core/src/main/java/org/springframework/security/authorization/method/SecuredAuthorizationManager.java b/core/src/main/java/org/springframework/security/authorization/method/SecuredAuthorizationManager.java deleted file mode 100644 index b05529d6f9..0000000000 --- a/core/src/main/java/org/springframework/security/authorization/method/SecuredAuthorizationManager.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2002-2021 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.Method; -import java.util.function.Supplier; - -import org.aopalliance.intercept.MethodInvocation; - -import org.springframework.aop.support.AopUtils; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.lang.NonNull; -import org.springframework.security.access.annotation.Secured; -import org.springframework.security.authorization.AuthorityAuthorizationManager; -import org.springframework.security.authorization.AuthorizationDecision; -import org.springframework.security.authorization.AuthorizationManager; -import org.springframework.security.core.Authentication; - -/** - * An {@link AuthorizationManager} which can determine if an {@link Authentication} may - * invoke the {@link MethodInvocation} by evaluating if the {@link Authentication} - * contains a specified authority from the Spring Security's {@link Secured} annotation. - * - * @author Evgeniy Cheban - * @since 5.5 - */ -public final class SecuredAuthorizationManager implements AuthorizationManager { - - private final SecuredAuthorizationManagerRegistry registry = new SecuredAuthorizationManagerRegistry(); - - /** - * Determine if an {@link Authentication} has access to a method by evaluating the - * {@link Secured} annotation that {@link AuthorizationMethodInvocation} specifies. - * @param authentication the {@link Supplier} of the {@link Authentication} to check - * @param mi the {@link AuthorizationMethodInvocation} to check - * @return an {@link AuthorizationDecision} or null if the {@link Secured} annotation - * is not present - */ - @Override - public AuthorizationDecision check(Supplier authentication, MethodInvocation mi) { - AuthorizationManager delegate = this.registry.getManager((AuthorizationMethodInvocation) mi); - return delegate.check(authentication, mi); - } - - private static final class SecuredAuthorizationManagerRegistry extends AbstractAuthorizationManagerRegistry { - - @NonNull - @Override - AuthorizationManager resolveManager(Method method, Class targetClass) { - Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass); - Secured secured = findSecuredAnnotation(specificMethod); - return (secured != null) ? AuthorityAuthorizationManager.hasAnyAuthority(secured.value()) : NULL_MANAGER; - } - - private Secured findSecuredAnnotation(Method method) { - Secured secured = AnnotationUtils.findAnnotation(method, Secured.class); - return (secured != null) ? secured - : AnnotationUtils.findAnnotation(method.getDeclaringClass(), Secured.class); - } - - } - -} diff --git a/core/src/test/java/org/springframework/security/authorization/AuthorityAuthorizationManagerTests.java b/core/src/test/java/org/springframework/security/authorization/AuthorityAuthorizationManagerTests.java index 5c092d54d4..ab0c41563c 100644 --- a/core/src/test/java/org/springframework/security/authorization/AuthorityAuthorizationManagerTests.java +++ b/core/src/test/java/org/springframework/security/authorization/AuthorityAuthorizationManagerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2020 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. @@ -64,13 +64,6 @@ public class AuthorityAuthorizationManagerTests { .withMessage("roles cannot contain null values"); } - @Test - public void hasAnyRoleWhenCustomRolePrefixNullThenException() { - assertThatIllegalArgumentException() - .isThrownBy(() -> AuthorityAuthorizationManager.hasAnyRole(null, new String[] { "ADMIN", "USER" })) - .withMessage("rolePrefix cannot be null"); - } - @Test public void hasAnyAuthorityWhenNullThenException() { assertThatIllegalArgumentException().isThrownBy(() -> AuthorityAuthorizationManager.hasAnyAuthority(null)) @@ -154,17 +147,6 @@ public class AuthorityAuthorizationManagerTests { assertThat(manager.check(authentication, object).isGranted()).isFalse(); } - @Test - public void hasAnyRoleWhenCustomRolePrefixProvidedThenUseCustomRolePrefix() { - AuthorityAuthorizationManager manager = AuthorityAuthorizationManager.hasAnyRole("CUSTOM_", - new String[] { "USER" }); - Supplier authentication = () -> new TestingAuthenticationToken("user", "password", - "CUSTOM_USER"); - Object object = new Object(); - - assertThat(manager.check(authentication, object).isGranted()).isTrue(); - } - @Test public void hasAnyAuthorityWhenUserHasAnyAuthorityThenGrantedDecision() { AuthorityAuthorizationManager manager = AuthorityAuthorizationManager.hasAnyAuthority("ADMIN", "USER"); diff --git a/core/src/test/java/org/springframework/security/authorization/method/AuthorizationManagerAfterMethodInterceptorTests.java b/core/src/test/java/org/springframework/security/authorization/method/AuthorizationManagerAfterMethodInterceptorTests.java deleted file mode 100644 index 0c0519a3c3..0000000000 --- a/core/src/test/java/org/springframework/security/authorization/method/AuthorizationManagerAfterMethodInterceptorTests.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2002-2021 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.util.function.Supplier; - -import org.aopalliance.intercept.MethodInvocation; -import org.junit.Test; - -import org.springframework.aop.Pointcut; -import org.springframework.security.authentication.TestAuthentication; -import org.springframework.security.core.Authentication; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -/** - * Tests for {@link AuthorizationManagerAfterMethodInterceptor}. - * - * @author Evgeniy Cheban - */ -public class AuthorizationManagerAfterMethodInterceptorTests { - - @Test - public void instantiateWhenMethodMatcherNullThenException() { - AfterMethodAuthorizationManager mockAuthorizationManager = mock( - AfterMethodAuthorizationManager.class); - assertThatIllegalArgumentException() - .isThrownBy(() -> new AuthorizationManagerAfterMethodInterceptor(null, mockAuthorizationManager)) - .withMessage("pointcut cannot be null"); - } - - @Test - public void instantiateWhenAuthorizationManagerNullThenException() { - assertThatIllegalArgumentException() - .isThrownBy(() -> new AuthorizationManagerAfterMethodInterceptor(mock(Pointcut.class), null)) - .withMessage("authorizationManager cannot be null"); - } - - @Test - public void beforeWhenMockAuthorizationManagerThenVerifyAndReturnedObject() throws Throwable { - Supplier authentication = TestAuthentication::authenticatedUser; - MethodInvocation mockMethodInvocation = mock(MethodInvocation.class); - Object returnedObject = new Object(); - given(mockMethodInvocation.proceed()).willReturn(returnedObject); - AfterMethodAuthorizationManager mockAuthorizationManager = mock( - AfterMethodAuthorizationManager.class); - AuthorizationManagerAfterMethodInterceptor advice = new AuthorizationManagerAfterMethodInterceptor( - Pointcut.TRUE, mockAuthorizationManager); - Object result = advice.invoke(authentication, mockMethodInvocation); - assertThat(result).isEqualTo(returnedObject); - verify(mockAuthorizationManager).verify(authentication, mockMethodInvocation, returnedObject); - } - -} diff --git a/core/src/test/java/org/springframework/security/authorization/method/AuthorizationManagerBeforeMethodInterceptorTests.java b/core/src/test/java/org/springframework/security/authorization/method/AuthorizationManagerBeforeMethodInterceptorTests.java deleted file mode 100644 index f205d75d43..0000000000 --- a/core/src/test/java/org/springframework/security/authorization/method/AuthorizationManagerBeforeMethodInterceptorTests.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2002-2021 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.util.function.Supplier; - -import org.aopalliance.intercept.MethodInvocation; -import org.junit.Test; - -import org.springframework.aop.Pointcut; -import org.springframework.security.authentication.TestAuthentication; -import org.springframework.security.authorization.AuthorizationManager; -import org.springframework.security.core.Authentication; - -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -/** - * Tests for {@link AuthorizationManagerBeforeMethodInterceptor}. - * - * @author Evgeniy Cheban - */ -public class AuthorizationManagerBeforeMethodInterceptorTests { - - @Test - public void instantiateWhenMethodMatcherNullThenException() { - assertThatIllegalArgumentException() - .isThrownBy( - () -> new AuthorizationManagerBeforeMethodInterceptor(null, mock(AuthorizationManager.class))) - .withMessage("pointcut cannot be null"); - } - - @Test - public void instantiateWhenAuthorizationManagerNullThenException() { - assertThatIllegalArgumentException() - .isThrownBy(() -> new AuthorizationManagerBeforeMethodInterceptor(mock(Pointcut.class), null)) - .withMessage("authorizationManager cannot be null"); - } - - @Test - public void beforeWhenMockAuthorizationManagerThenVerify() throws Throwable { - Supplier authentication = TestAuthentication::authenticatedUser; - MethodInvocation mockMethodInvocation = mock(MethodInvocation.class); - AuthorizationManager mockAuthorizationManager = mock(AuthorizationManager.class); - AuthorizationManagerBeforeMethodInterceptor advice = new AuthorizationManagerBeforeMethodInterceptor( - Pointcut.TRUE, mockAuthorizationManager); - advice.invoke(authentication, mockMethodInvocation); - verify(mockAuthorizationManager).verify(authentication, mockMethodInvocation); - } - -} diff --git a/core/src/test/java/org/springframework/security/authorization/method/AuthorizationMethodPointcutsTests.java b/core/src/test/java/org/springframework/security/authorization/method/AuthorizationMethodPointcutsTests.java deleted file mode 100644 index b2bb8de7b3..0000000000 --- a/core/src/test/java/org/springframework/security/authorization/method/AuthorizationMethodPointcutsTests.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2002-2021 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.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.junit.Test; - -import org.springframework.aop.Pointcut; -import org.springframework.aop.support.AopUtils; -import org.springframework.security.access.prepost.PreAuthorize; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link AuthorizationMethodPointcuts} - */ -public class AuthorizationMethodPointcutsTests { - - @Test - public void forAnnotationsWhenAnnotationThenClassBasedAnnotationPointcut() { - Pointcut preAuthorize = AuthorizationMethodPointcuts.forAnnotations(PreAuthorize.class); - assertThat(AopUtils.canApply(preAuthorize, ClassController.class)).isTrue(); - assertThat(AopUtils.canApply(preAuthorize, NoController.class)).isFalse(); - } - - @Test - public void forAnnotationsWhenAnnotationThenMethodBasedAnnotationPointcut() { - Pointcut preAuthorize = AuthorizationMethodPointcuts.forAnnotations(PreAuthorize.class); - assertThat(AopUtils.canApply(preAuthorize, MethodController.class)).isTrue(); - } - - @Test - public void forAnnotationsWhenAnnotationThenClassInheritancePointcut() { - Pointcut preAuthorize = AuthorizationMethodPointcuts.forAnnotations(PreAuthorize.class); - assertThat(AopUtils.canApply(preAuthorize, InterfacedClassController.class)).isTrue(); - } - - @Test - public void forAnnotationsWhenAnnotationThenMethodInheritancePointcut() { - Pointcut preAuthorize = AuthorizationMethodPointcuts.forAnnotations(PreAuthorize.class); - assertThat(AopUtils.canApply(preAuthorize, InterfacedMethodController.class)).isTrue(); - } - - @Test - public void forAnnotationsWhenAnnotationThenAnnotationClassInheritancePointcut() { - Pointcut preAuthorize = AuthorizationMethodPointcuts.forAnnotations(PreAuthorize.class); - assertThat(AopUtils.canApply(preAuthorize, InterfacedAnnotationClassController.class)).isTrue(); - } - - @Test - public void forAnnotationsWhenAnnotationThenAnnotationMethodInheritancePointcut() { - Pointcut preAuthorize = AuthorizationMethodPointcuts.forAnnotations(PreAuthorize.class); - assertThat(AopUtils.canApply(preAuthorize, InterfacedAnnotationMethodController.class)).isTrue(); - } - - @PreAuthorize("hasAuthority('APP')") - public static class ClassController { - - String methodOne(String paramOne) { - return "value"; - } - - } - - public static class MethodController { - - @PreAuthorize("hasAuthority('APP')") - String methodOne(String paramOne) { - return "value"; - } - - } - - public static class NoController { - - String methodOne(String paramOne) { - return "value"; - } - - } - - @PreAuthorize("hasAuthority('APP')") - public interface ClassControllerInterface { - - String methodOne(String paramOne); - - } - - public static class InterfacedClassController implements ClassControllerInterface { - - public String methodOne(String paramOne) { - return "value"; - } - - } - - public interface MethodControllerInterface { - - @PreAuthorize("hasAuthority('APP')") - String methodOne(String paramOne); - - } - - public static class InterfacedMethodController implements MethodControllerInterface { - - public String methodOne(String paramOne) { - return "value"; - } - - } - - @Target({ ElementType.METHOD, ElementType.TYPE }) - @Retention(RetentionPolicy.RUNTIME) - @PreAuthorize("hasAuthority('APP')") - @interface MyAnnotation { - - } - - @MyAnnotation - public interface ClassAnnotationControllerInterface { - - String methodOne(String paramOne); - - } - - public static class InterfacedAnnotationClassController implements ClassAnnotationControllerInterface { - - public String methodOne(String paramOne) { - return "value"; - } - - } - - public interface MethodAnnotationControllerInterface { - - @MyAnnotation - String methodOne(String paramOne); - - } - - public static class InterfacedAnnotationMethodController implements MethodAnnotationControllerInterface { - - public String methodOne(String paramOne) { - return "value"; - } - - } - -} diff --git a/core/src/test/java/org/springframework/security/authorization/method/DelegatingAuthorizationMethodInterceptorTests.java b/core/src/test/java/org/springframework/security/authorization/method/DelegatingAuthorizationMethodInterceptorTests.java deleted file mode 100644 index 6ee0d066b0..0000000000 --- a/core/src/test/java/org/springframework/security/authorization/method/DelegatingAuthorizationMethodInterceptorTests.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2002-2021 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.util.Arrays; -import java.util.function.Supplier; - -import org.aopalliance.intercept.MethodInvocation; -import org.junit.After; -import org.junit.Test; - -import org.springframework.aop.Pointcut; -import org.springframework.security.access.intercept.method.MockMethodInvocation; -import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; -import org.springframework.security.authentication.TestAuthentication; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.context.SecurityContextImpl; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -/** - * Tests for {@link DelegatingAuthorizationMethodInterceptor}. - * - * @author Evgeniy Cheban - */ -public class DelegatingAuthorizationMethodInterceptorTests { - - @After - public void tearDown() { - SecurityContextHolder.clearContext(); - } - - @Test - public void invokeWhenAuthenticatedThenVerifyAdvicesUsage() throws Throwable { - Authentication authentication = TestAuthentication.authenticatedUser(); - SecurityContextHolder.setContext(new SecurityContextImpl(authentication)); - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomethingString"); - AuthorizationMethodInterceptor interceptor = mock(AuthorizationMethodInterceptor.class); - given(interceptor.getPointcut()).willReturn(Pointcut.TRUE); - given(interceptor.invoke(any(), any(AuthorizationMethodInvocation.class))).willReturn("abc"); - DelegatingAuthorizationMethodInterceptor chain = new DelegatingAuthorizationMethodInterceptor( - Arrays.asList(interceptor)); - Object result = chain.invoke(mockMethodInvocation); - assertThat(result).isEqualTo("abc"); - verify(interceptor).invoke(any(), any(AuthorizationMethodInvocation.class)); - } - - @Test - public void invokeWhenNotAuthenticatedThenAuthenticationCredentialsNotFoundException() throws Throwable { - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomethingString"); - AuthorizationMethodInterceptor first = new AuthorizationMethodInterceptor() { - @Override - public Pointcut getPointcut() { - return Pointcut.TRUE; - } - - @Override - public Object invoke(Supplier authentication, MethodInvocation mi) { - return authentication.get(); - } - }; - AuthorizationMethodInterceptor second = mock(AuthorizationMethodInterceptor.class); - given(second.getPointcut()).willReturn(Pointcut.TRUE); - DelegatingAuthorizationMethodInterceptor interceptor = new DelegatingAuthorizationMethodInterceptor( - Arrays.asList(first, second)); - assertThatExceptionOfType(AuthenticationCredentialsNotFoundException.class) - .isThrownBy(() -> interceptor.invoke(mockMethodInvocation)) - .withMessage("An Authentication object was not found in the SecurityContext"); - verify(second, times(0)).invoke(any(), any()); - } - - public static class TestClass { - - public String doSomethingString() { - return null; - } - - } - -} 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 deleted file mode 100644 index 0b9c63e708..0000000000 --- a/core/src/test/java/org/springframework/security/authorization/method/Jsr250AuthorizationManagerTests.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright 2002-2021 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.util.Collections; -import java.util.function.Supplier; - -import javax.annotation.security.DenyAll; -import javax.annotation.security.PermitAll; -import javax.annotation.security.RolesAllowed; - -import org.junit.Test; - -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.AuthorizationDecision; -import org.springframework.security.core.Authentication; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; - -/** - * Tests for {@link Jsr250AuthorizationManager}. - * - * @author Evgeniy Cheban - */ -public class Jsr250AuthorizationManagerTests { - - @Test - public void rolePrefixWhenNotSetThenDefaultsToRole() { - Jsr250AuthorizationManager manager = new Jsr250AuthorizationManager(); - assertThat(manager).extracting("rolePrefix").isEqualTo("ROLE_"); - } - - @Test - public void setRolePrefixWhenNullThenException() { - Jsr250AuthorizationManager manager = new Jsr250AuthorizationManager(); - assertThatIllegalArgumentException().isThrownBy(() -> manager.setRolePrefix(null)) - .withMessage("rolePrefix cannot be null"); - } - - @Test - public void setRolePrefixWhenNotNullThenSets() { - Jsr250AuthorizationManager manager = new Jsr250AuthorizationManager(); - manager.setRolePrefix("CUSTOM_"); - assertThat(manager).extracting("rolePrefix").isEqualTo("CUSTOM_"); - } - - @Test - public void checkDoSomethingWhenNoJsr250AnnotationsThenNullDecision() throws Exception { - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomething"); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - Jsr250AuthorizationManager manager = new Jsr250AuthorizationManager(); - AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, methodInvocation); - assertThat(decision).isNull(); - } - - @Test - public void checkPermitAllRolesAllowedAdminWhenRoleUserThenGrantedDecision() throws Exception { - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "permitAllRolesAllowedAdmin"); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - Jsr250AuthorizationManager manager = new Jsr250AuthorizationManager(); - AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, methodInvocation); - assertThat(decision).isNotNull(); - assertThat(decision.isGranted()).isTrue(); - } - - @Test - public void checkDenyAllRolesAllowedAdminWhenRoleAdminThenDeniedDecision() throws Exception { - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "denyAllRolesAllowedAdmin"); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - Jsr250AuthorizationManager manager = new Jsr250AuthorizationManager(); - AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedAdmin, methodInvocation); - assertThat(decision).isNotNull(); - assertThat(decision.isGranted()).isFalse(); - } - - @Test - public void checkRolesAllowedUserOrAdminWhenRoleUserThenGrantedDecision() throws Exception { - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "rolesAllowedUserOrAdmin"); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - Jsr250AuthorizationManager manager = new Jsr250AuthorizationManager(); - AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, methodInvocation); - assertThat(decision).isNotNull(); - assertThat(decision.isGranted()).isTrue(); - } - - @Test - public void checkRolesAllowedUserOrAdminWhenRoleAdminThenGrantedDecision() throws Exception { - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "rolesAllowedUserOrAdmin"); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - Jsr250AuthorizationManager manager = new Jsr250AuthorizationManager(); - AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedAdmin, methodInvocation); - assertThat(decision).isNotNull(); - assertThat(decision.isGranted()).isTrue(); - } - - @Test - public void checkRolesAllowedUserOrAdminWhenRoleAnonymousThenDeniedDecision() throws Exception { - Supplier authentication = () -> new TestingAuthenticationToken("user", "password", - "ROLE_ANONYMOUS"); - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "rolesAllowedUserOrAdmin"); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - Jsr250AuthorizationManager manager = new Jsr250AuthorizationManager(); - AuthorizationDecision decision = manager.check(authentication, methodInvocation); - assertThat(decision).isNotNull(); - assertThat(decision.isGranted()).isFalse(); - } - - public static class TestClass { - - public void doSomething() { - - } - - @DenyAll - @RolesAllowed("ADMIN") - public void denyAllRolesAllowedAdmin() { - - } - - @PermitAll - @RolesAllowed("ADMIN") - public void permitAllRolesAllowedAdmin() { - - } - - @RolesAllowed({ "USER", "ADMIN" }) - public void rolesAllowedUserOrAdmin() { - - } - - } - -} 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 deleted file mode 100644 index 4726304056..0000000000 --- a/core/src/test/java/org/springframework/security/authorization/method/PostAuthorizeAuthorizationManagerTests.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2002-2021 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.util.Arrays; -import java.util.Collections; -import java.util.List; - -import org.junit.Test; - -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.authorization.AuthorizationDecision; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; - -/** - * Tests for {@link PostAuthorizeAuthorizationManager}. - * - * @author Evgeniy Cheban - */ -public class PostAuthorizeAuthorizationManagerTests { - - @Test - public void setExpressionHandlerWhenNotNullThenSetsExpressionHandler() { - MethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler(); - PostAuthorizeAuthorizationManager manager = new PostAuthorizeAuthorizationManager(); - manager.setExpressionHandler(expressionHandler); - assertThat(manager).extracting("expressionHandler").isEqualTo(expressionHandler); - } - - @Test - public void setExpressionHandlerWhenNullThenException() { - PostAuthorizeAuthorizationManager manager = new PostAuthorizeAuthorizationManager(); - assertThatIllegalArgumentException().isThrownBy(() -> manager.setExpressionHandler(null)) - .withMessage("expressionHandler cannot be null"); - } - - @Test - public void checkDoSomethingWhenNoPostAuthorizeAnnotationThenNullDecision() throws Exception { - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomething", new Class[] {}, new Object[] {}); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - PostAuthorizeAuthorizationManager manager = new PostAuthorizeAuthorizationManager(); - AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, methodInvocation, null); - assertThat(decision).isNull(); - } - - @Test - public void checkDoSomethingStringWhenArgIsGrantThenGrantedDecision() throws Exception { - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomethingString", new Class[] { String.class }, new Object[] { "grant" }); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - PostAuthorizeAuthorizationManager manager = new PostAuthorizeAuthorizationManager(); - AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, methodInvocation, null); - assertThat(decision).isNotNull(); - assertThat(decision.isGranted()).isTrue(); - } - - @Test - public void checkDoSomethingStringWhenArgIsNotGrantThenDeniedDecision() throws Exception { - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomethingString", new Class[] { String.class }, new Object[] { "deny" }); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - PostAuthorizeAuthorizationManager manager = new PostAuthorizeAuthorizationManager(); - AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, methodInvocation, null); - assertThat(decision).isNotNull(); - assertThat(decision.isGranted()).isFalse(); - } - - @Test - public void checkDoSomethingListWhenReturnObjectContainsGrantThenGrantedDecision() throws Exception { - List list = Arrays.asList("grant", "deny"); - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomethingList", new Class[] { List.class }, new Object[] { list }); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - PostAuthorizeAuthorizationManager manager = new PostAuthorizeAuthorizationManager(); - AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, methodInvocation, list); - assertThat(decision).isNotNull(); - assertThat(decision.isGranted()).isTrue(); - } - - @Test - public void checkDoSomethingListWhenReturnObjectNotContainsGrantThenDeniedDecision() throws Exception { - List list = Collections.singletonList("deny"); - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomethingList", new Class[] { List.class }, new Object[] { list }); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - PostAuthorizeAuthorizationManager manager = new PostAuthorizeAuthorizationManager(); - AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, methodInvocation, list); - assertThat(decision).isNotNull(); - assertThat(decision.isGranted()).isFalse(); - } - - public static class TestClass { - - public void doSomething() { - - } - - @PostAuthorize("#s == 'grant'") - public String doSomethingString(String s) { - return s; - } - - @PostAuthorize("returnObject.contains('grant')") - public List doSomethingList(List list) { - return list; - } - - } - -} 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 deleted file mode 100644 index a792b5d1a5..0000000000 --- a/core/src/test/java/org/springframework/security/authorization/method/PostFilterAuthorizationMethodInterceptorTests.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2002-2021 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.util.Collections; - -import org.assertj.core.api.InstanceOfAssertFactories; -import org.junit.Test; - -import org.springframework.aop.MethodMatcher; -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 static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; - -/** - * Tests for {@link PostFilterAuthorizationMethodInterceptor}. - * - * @author Evgeniy Cheban - */ -public class PostFilterAuthorizationMethodInterceptorTests { - - @Test - public void setExpressionHandlerWhenNotNullThenSetsExpressionHandler() { - MethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler(); - PostFilterAuthorizationMethodInterceptor advice = new PostFilterAuthorizationMethodInterceptor(); - advice.setExpressionHandler(expressionHandler); - assertThat(advice).extracting("expressionHandler").isEqualTo(expressionHandler); - } - - @Test - public void setExpressionHandlerWhenNullThenException() { - PostFilterAuthorizationMethodInterceptor advice = new PostFilterAuthorizationMethodInterceptor(); - assertThatIllegalArgumentException().isThrownBy(() -> advice.setExpressionHandler(null)) - .withMessage("expressionHandler cannot be null"); - } - - @Test - public void methodMatcherWhenMethodHasNotPostFilterAnnotationThenNotMatches() throws Exception { - PostFilterAuthorizationMethodInterceptor advice = new PostFilterAuthorizationMethodInterceptor(); - MethodMatcher methodMatcher = advice.getPointcut().getMethodMatcher(); - assertThat(methodMatcher.matches(NoPostFilterClass.class.getMethod("doSomething"), NoPostFilterClass.class)) - .isFalse(); - } - - @Test - public void methodMatcherWhenMethodHasPostFilterAnnotationThenMatches() throws Exception { - PostFilterAuthorizationMethodInterceptor advice = new PostFilterAuthorizationMethodInterceptor(); - MethodMatcher methodMatcher = advice.getPointcut().getMethodMatcher(); - assertThat( - methodMatcher.matches(TestClass.class.getMethod("doSomethingArray", String[].class), TestClass.class)) - .isTrue(); - } - - @Test - public void afterWhenArrayNotNullThenFilteredArray() throws Throwable { - String[] array = { "john", "bob" }; - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomethingArrayClassLevel", new Class[] { String[].class }, new Object[] { array }) { - @Override - public Object proceed() { - return array; - } - }; - PostFilterAuthorizationMethodInterceptor advice = new PostFilterAuthorizationMethodInterceptor(); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - Object result = advice.invoke(TestAuthentication::authenticatedUser, methodInvocation); - assertThat(result).asInstanceOf(InstanceOfAssertFactories.array(String[].class)).containsOnly("john"); - } - - @PostFilter("filterObject == 'john'") - public static class TestClass { - - @PostFilter("filterObject == 'john'") - public String[] doSomethingArray(String[] array) { - return array; - } - - public String[] doSomethingArrayClassLevel(String[] array) { - return array; - } - - } - - public static class NoPostFilterClass { - - public void doSomething() { - - } - - } - -} 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 deleted file mode 100644 index b38c48c6bf..0000000000 --- a/core/src/test/java/org/springframework/security/authorization/method/PreAuthorizeAuthorizationManagerTests.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2002-2021 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.util.Collections; - -import org.junit.Test; - -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.authorization.AuthorizationDecision; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; - -/** - * Tests for {@link PreAuthorizeAuthorizationManager}. - * - * @author Evgeniy Cheban - */ -public class PreAuthorizeAuthorizationManagerTests { - - @Test - public void setExpressionHandlerWhenNotNullThenSetsExpressionHandler() { - MethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler(); - PreAuthorizeAuthorizationManager manager = new PreAuthorizeAuthorizationManager(); - manager.setExpressionHandler(expressionHandler); - assertThat(manager).extracting("expressionHandler").isEqualTo(expressionHandler); - } - - @Test - public void setExpressionHandlerWhenNullThenException() { - PreAuthorizeAuthorizationManager manager = new PreAuthorizeAuthorizationManager(); - assertThatIllegalArgumentException().isThrownBy(() -> manager.setExpressionHandler(null)) - .withMessage("expressionHandler cannot be null"); - } - - @Test - public void checkDoSomethingWhenNoPostAuthorizeAnnotationThenNullDecision() throws Exception { - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomething", new Class[] {}, new Object[] {}); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - PreAuthorizeAuthorizationManager manager = new PreAuthorizeAuthorizationManager(); - AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, methodInvocation); - assertThat(decision).isNull(); - } - - @Test - public void checkDoSomethingStringWhenArgIsGrantThenGrantedDecision() throws Exception { - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomethingString", new Class[] { String.class }, new Object[] { "grant" }); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - PreAuthorizeAuthorizationManager manager = new PreAuthorizeAuthorizationManager(); - AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, methodInvocation); - assertThat(decision).isNotNull(); - assertThat(decision.isGranted()).isTrue(); - } - - @Test - public void checkDoSomethingStringWhenArgIsNotGrantThenDeniedDecision() throws Exception { - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomethingString", new Class[] { String.class }, new Object[] { "deny" }); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - PreAuthorizeAuthorizationManager manager = new PreAuthorizeAuthorizationManager(); - AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, methodInvocation); - assertThat(decision).isNotNull(); - assertThat(decision.isGranted()).isFalse(); - } - - public static class TestClass { - - public void doSomething() { - - } - - @PreAuthorize("#s == 'grant'") - public String doSomethingString(String s) { - return s; - } - - } - -} 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 deleted file mode 100644 index b9d54d8974..0000000000 --- a/core/src/test/java/org/springframework/security/authorization/method/PreFilterAuthorizationMethodInterceptorTests.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright 2002-2021 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.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.junit.Test; - -import org.springframework.aop.MethodMatcher; -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 static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -import static org.assertj.core.api.Assertions.assertThatIllegalStateException; - -/** - * Tests for {@link PreFilterAuthorizationMethodInterceptor}. - * - * @author Evgeniy Cheban - */ -public class PreFilterAuthorizationMethodInterceptorTests { - - @Test - public void setExpressionHandlerWhenNotNullThenSetsExpressionHandler() { - MethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler(); - PreFilterAuthorizationMethodInterceptor advice = new PreFilterAuthorizationMethodInterceptor(); - advice.setExpressionHandler(expressionHandler); - assertThat(advice).extracting("expressionHandler").isEqualTo(expressionHandler); - } - - @Test - public void setExpressionHandlerWhenNullThenException() { - PreFilterAuthorizationMethodInterceptor advice = new PreFilterAuthorizationMethodInterceptor(); - assertThatIllegalArgumentException().isThrownBy(() -> advice.setExpressionHandler(null)) - .withMessage("expressionHandler cannot be null"); - } - - @Test - public void methodMatcherWhenMethodHasNotPreFilterAnnotationThenNotMatches() throws Exception { - PreFilterAuthorizationMethodInterceptor advice = new PreFilterAuthorizationMethodInterceptor(); - MethodMatcher methodMatcher = advice.getPointcut().getMethodMatcher(); - assertThat(methodMatcher.matches(NoPreFilterClass.class.getMethod("doSomething"), NoPreFilterClass.class)) - .isFalse(); - } - - @Test - public void methodMatcherWhenMethodHasPreFilterAnnotationThenMatches() throws Exception { - PreFilterAuthorizationMethodInterceptor advice = new PreFilterAuthorizationMethodInterceptor(); - MethodMatcher methodMatcher = advice.getPointcut().getMethodMatcher(); - assertThat(methodMatcher.matches(TestClass.class.getMethod("doSomethingListFilterTargetMatch", List.class), - TestClass.class)).isTrue(); - } - - @Test - public void findFilterTargetWhenNameProvidedAndNotMatchThenException() throws Exception { - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomethingListFilterTargetNotMatch", new Class[] { List.class }, new Object[] { new ArrayList<>() }); - PreFilterAuthorizationMethodInterceptor advice = new PreFilterAuthorizationMethodInterceptor(); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - assertThatIllegalArgumentException() - .isThrownBy(() -> advice.invoke(TestAuthentication::authenticatedUser, methodInvocation)).withMessage( - "Filter target was null, or no argument with name 'filterTargetNotMatch' found in method."); - } - - @Test - public void findFilterTargetWhenNameProvidedAndMatchAndNullThenException() throws Exception { - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomethingListFilterTargetMatch", new Class[] { List.class }, new Object[] { null }); - PreFilterAuthorizationMethodInterceptor advice = new PreFilterAuthorizationMethodInterceptor(); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - assertThatIllegalArgumentException() - .isThrownBy(() -> advice.invoke(TestAuthentication::authenticatedUser, methodInvocation)) - .withMessage("Filter target was null, or no argument with name 'list' found in method."); - } - - @Test - public void findFilterTargetWhenNameProvidedAndMatchAndNotNullThenFiltersList() throws Throwable { - List list = new ArrayList<>(); - list.add("john"); - list.add("bob"); - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomethingListFilterTargetMatch", new Class[] { List.class }, new Object[] { list }); - PreFilterAuthorizationMethodInterceptor advice = new PreFilterAuthorizationMethodInterceptor(); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - advice.invoke(TestAuthentication::authenticatedUser, methodInvocation); - assertThat(list).hasSize(1); - assertThat(list.get(0)).isEqualTo("john"); - } - - @Test - public void findFilterTargetWhenNameNotProvidedAndSingleArgListNullThenException() throws Exception { - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomethingListFilterTargetNotProvided", new Class[] { List.class }, new Object[] { null }); - PreFilterAuthorizationMethodInterceptor advice = new PreFilterAuthorizationMethodInterceptor(); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - assertThatIllegalArgumentException() - .isThrownBy(() -> advice.invoke(TestAuthentication::authenticatedUser, methodInvocation)) - .withMessage("Filter target was null. Make sure you passing the correct value in the method argument."); - } - - @Test - public void findFilterTargetWhenNameNotProvidedAndSingleArgListThenFiltersList() throws Throwable { - List list = new ArrayList<>(); - list.add("john"); - list.add("bob"); - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomethingListFilterTargetNotProvided", new Class[] { List.class }, new Object[] { list }); - PreFilterAuthorizationMethodInterceptor advice = new PreFilterAuthorizationMethodInterceptor(); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - advice.invoke(TestAuthentication::authenticatedUser, methodInvocation); - assertThat(list).hasSize(1); - assertThat(list.get(0)).isEqualTo("john"); - } - - @Test - public void findFilterTargetWhenNameNotProvidedAndSingleArgArrayThenException() throws Exception { - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomethingArrayFilterTargetNotProvided", new Class[] { String[].class }, - new Object[] { new String[] {} }); - PreFilterAuthorizationMethodInterceptor advice = new PreFilterAuthorizationMethodInterceptor(); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - assertThatIllegalStateException() - .isThrownBy(() -> advice.invoke(TestAuthentication::authenticatedUser, methodInvocation)).withMessage( - "Pre-filtering on array types is not supported. Using a Collection will solve this problem."); - } - - @Test - public void findFilterTargetWhenNameNotProvidedAndNotSingleArgThenException() throws Exception { - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomethingTwoArgsFilterTargetNotProvided", new Class[] { String.class, List.class }, - new Object[] { "", new ArrayList<>() }); - PreFilterAuthorizationMethodInterceptor advice = new PreFilterAuthorizationMethodInterceptor(); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - assertThatIllegalStateException() - .isThrownBy(() -> advice.invoke(TestAuthentication::authenticatedUser, methodInvocation)) - .withMessage("Unable to determine the method argument for filtering. Specify the filter target."); - } - - @PreFilter("filterObject == 'john'") - public static class TestClass { - - @PreFilter(value = "filterObject == 'john'", filterTarget = "filterTargetNotMatch") - public List doSomethingListFilterTargetNotMatch(List list) { - return list; - } - - @PreFilter(value = "filterObject == 'john'", filterTarget = "list") - public List doSomethingListFilterTargetMatch(List list) { - return list; - } - - @PreFilter("filterObject == 'john'") - public List doSomethingListFilterTargetNotProvided(List list) { - return list; - } - - @PreFilter("filterObject == 'john'") - public String[] doSomethingArrayFilterTargetNotProvided(String[] array) { - return array; - } - - public List doSomethingTwoArgsFilterTargetNotProvided(String s, List list) { - return list; - } - - } - - public static class NoPreFilterClass { - - public void doSomething() { - - } - - } - -} 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 deleted file mode 100644 index 076fdf473a..0000000000 --- a/core/src/test/java/org/springframework/security/authorization/method/SecuredAuthorizationManagerTests.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2002-2021 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.util.Collections; -import java.util.function.Supplier; - -import org.junit.Test; - -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.AuthorizationDecision; -import org.springframework.security.core.Authentication; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link SecuredAuthorizationManager}. - * - * @author Evgeniy Cheban - */ -public class SecuredAuthorizationManagerTests { - - @Test - public void checkDoSomethingWhenNoSecuredAnnotationThenNullDecision() throws Exception { - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomething"); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - SecuredAuthorizationManager manager = new SecuredAuthorizationManager(); - AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, methodInvocation); - assertThat(decision).isNull(); - } - - @Test - public void checkSecuredUserOrAdminWhenRoleUserThenGrantedDecision() throws Exception { - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "securedUserOrAdmin"); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedUser, mockMethodInvocation, Collections.emptyList()); - SecuredAuthorizationManager manager = new SecuredAuthorizationManager(); - AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedUser, methodInvocation); - assertThat(decision).isNotNull(); - assertThat(decision.isGranted()).isTrue(); - } - - @Test - public void checkSecuredUserOrAdminWhenRoleAdminThenGrantedDecision() throws Exception { - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "securedUserOrAdmin"); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation( - TestAuthentication::authenticatedAdmin, mockMethodInvocation, Collections.emptyList()); - SecuredAuthorizationManager manager = new SecuredAuthorizationManager(); - AuthorizationDecision decision = manager.check(TestAuthentication::authenticatedAdmin, methodInvocation); - assertThat(decision).isNotNull(); - assertThat(decision.isGranted()).isTrue(); - } - - @Test - public void checkSecuredUserOrAdminWhenRoleAnonymousThenDeniedDecision() throws Exception { - Supplier authentication = () -> new TestingAuthenticationToken("user", "password", - "ROLE_ANONYMOUS"); - MockMethodInvocation mockMethodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "securedUserOrAdmin"); - AuthorizationMethodInvocation methodInvocation = new AuthorizationMethodInvocation(authentication, - mockMethodInvocation, Collections.emptyList()); - SecuredAuthorizationManager manager = new SecuredAuthorizationManager(); - AuthorizationDecision decision = manager.check(authentication, methodInvocation); - assertThat(decision).isNotNull(); - assertThat(decision.isGranted()).isFalse(); - } - - public static class TestClass { - - public void doSomething() { - - } - - @Secured({ "ROLE_USER", "ROLE_ADMIN" }) - public void securedUserOrAdmin() { - - } - - } - -} diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/authorization/method-security.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/authorization/method-security.adoc index 7c1d4304b6..573412f6bf 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/authorization/method-security.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/authorization/method-security.adoc @@ -6,185 +6,6 @@ It provides support for JSR-250 annotation security as well as the framework's o From 3.0 you can also make use of new <>. You can apply security to a single bean, using the `intercept-methods` element to decorate the bean declaration, or you can secure multiple beans across the entire service layer using the AspectJ style pointcuts. -=== EnableMethodSecurity - -In 5.5, we can enable annotation-based security using the `@EnableMethodSecurity` annotation on any `@Configuration` instance. - -[NOTE] -For earlier versions, please read about similar support with <>. - -For example, the following would enable Spring Security's `@PreAuthorize` annotation: - -[source,java] ----- -@EnableMethodSecurity -public class MethodSecurityConfig { - // ... -} ----- - -Adding an annotation to a method (on a class or interface) would then limit the access to that method accordingly. -Spring Security's native annotatino support defines a set of attributes for the method. -These will be passed to the `DefaultAuthorizationMethodInterceptorChain` for it to make the actual decision: - -[source,java] ----- -public interface BankService { - - @PreAuthorize("hasRole('USER')") - Account readAccount(Long id); - - @PreAuthorize("hasRole('USER')") - Account[] findAccounts(); - - @PreAuthorize("hasRole('TELLER')") - Account post(Account account, double amount); -} ----- - -You can enable support for Spring Security's `@Secured` annotation using: - -[source,java] ----- -@EnableMethodSecurity(secureEnabled = true) -public class MethodSecurityConfig { - // ... -} ----- - -or JSR-250 using: - -[source,java] ----- -@EnableMethodSecurity(jsr250Enabled = true) -public class MethodSecurityConfig { - // ... -} ----- - -==== Customizing Authorization - -Spring Security's `@PreAuthorize`, `@PostAuthorize`, `@PreFilter`, and `@PostFilter` ship with rich expression-based support. - -If you need to customize the way that expressions are handled, you can expose a custom `MethodSecurityExpressionHandler`, like so: - -[source,java] ----- -@Bean -MethodSecurityExpressionHandler methodSecurityExpressionHandler() { - DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler(); - handler.setTrustResolver(myCustomTrustResolver); - return handler; -} ----- - -Also, for role-based authorization, Spring Security adds a default `ROLE_` prefix, which is uses when evaluating expressions like `hasRole`. - -You can configure the authorization rules to use a different prefix by exposing a `GrantedAuthorityDefaults` bean, like so: - -[source,java] ----- -@Bean -GrantedAuthorityDefaults grantedAuthorityDefaults() { - return new GrantedAuthorityDefaults("MYPREFIX_"); -} ----- - -==== Custom Authorization Managers - -Method authorization is a combination of before- and after-method authorization. - -[NOTE] -Before-method authorization is performed before the method is invoked. -If that authorization denies access, the method is not invoked and an `AccessDeniedException` is thrown -After-method authorization is performed after the method is invoked, but before the method returns to the caller. -If that authorization denies access, the value is not returned and an `AccessDeniedException` is thrown - -To recreate what Spring Security does by default, you would publish the following bean: - -[source,java] ----- -@Bean -public List methodSecurity() { - return new DelegatingAuthorizationMethodInterceptor( - new PreFilterAuthorizationMethodInterceptor(), // before-method - AuthorizationMethodInterceptors.preAuthorize(), // before-method - new PostFilterAuthorizationMethodInterceptor(), // after-method - AuthorizationMethodInterceptors.postAuthorize() // after-method - ); -} ----- - -[NOTE] -Keep in mind that publishing a list of `AuthorizationMethodInterceptor`s will completely replace any Spring Security defaults. - -Interceptors are invoked in the order that they are declared. - -You may want to only support `@PreAuthorize` in your application, in which case you can do the following: - -[source,java] ----- -@Bean -public AuthorizationMethodInterceptor methodSecurity() { - return AuthorizationMethodInterceptors.preAuthorize(); -} ----- - -Or, you may have a custom before-method `AuthorizationManager` that you want to add to the list. - -In this case, you will need to tell Spring Security both the `AuthorizationManager` and to which methods and classes your authorization manager applies. - -Spring Security integrates with Spring AOP to achieve this. -Thus, you can configure Spring Security to support `@PreAuthorize`, `@PostAuthorize`, and your own `AuthorizationManager` like so: - -[source,java] ----- -@Bean -public AuthorizationMethodInterceptor methodSecurity() { - JdkRegexpMethodPointcut pattern = new JdkRegexpMethodPointcut(); - pattern.setPattern("org.mycompany.myapp.service.*"); - AuthorizationManager rule = AuthorityAuthorizationManager.isAuthenticated(); - return new DelegatingAuthorizationMethodInterceptor( - AuthorizationMethodInterceptors.preAuthorize(), - new AuthorizationManagerBeforeMethodInterceptor(pattern, rule), - AuthorizationMethodInterceptors.postAuthorize() - ); -} ----- - -The same can be done for after-method authorization and `AfterMethodAuthorizationManager`. -After-method authorization is generally concerned with analysing the return value to verify access. - -For example, you might have a method that confirms that the account requested actually belongs to the logged-in user like so: - -[source,java] ----- -public interface BankService { - - @PreAuthorize("hasRole('USER')") - @PostAuthorize("returnObject.owner == authentication.name") - Account readAccount(Long id); -} ----- - -You can supply your own `AuthorizationMethodInterceptor` to customize how access to the return value is evaluated. - -For example, instead of embedding a great deal of logic into the `@PostAuthorize` SpEL expression, you may want to wire your own `@Bean`. -In that case, you can configure it like so: - -[source,java] ----- -@Bean -public AuthorizationMethodInterceptor methodSecurity - (AfterMethodAuthorizationManager rules) { - AnnotationMethodMatcher pattern = new AnnotationMethodMatcher(MySecurityAnnotation.class); - return new DelegatingAuthorizationMethodInterceptor( - AuthorizationMethodInterceptors.preAuthorize(), - new AuthorizationManagerAfterMethodInterceptor(pattern, rules)); -} ----- - -[[jc-enable-global-method-security]] === EnableGlobalMethodSecurity We can enable annotation-based security using the `@EnableGlobalMethodSecurity` annotation on any `@Configuration` instance.