Add check for custom advice
- Because publishing an advice bean replaces Spring Security defaults, the code should error if both a custom bean and either secureEnabled or prePostEnabled are specified Issue gh-9289
This commit is contained in:
parent
45376b359b
commit
68cf74468c
|
@ -36,6 +36,7 @@ import org.springframework.aop.support.AopUtils;
|
||||||
import org.springframework.aop.support.DefaultPointcutAdvisor;
|
import org.springframework.aop.support.DefaultPointcutAdvisor;
|
||||||
import org.springframework.aop.support.Pointcuts;
|
import org.springframework.aop.support.Pointcuts;
|
||||||
import org.springframework.aop.support.StaticMethodMatcher;
|
import org.springframework.aop.support.StaticMethodMatcher;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
@ -45,26 +46,27 @@ import org.springframework.context.annotation.Role;
|
||||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||||
import org.springframework.core.annotation.AnnotationAttributes;
|
import org.springframework.core.annotation.AnnotationAttributes;
|
||||||
import org.springframework.core.type.AnnotationMetadata;
|
import org.springframework.core.type.AnnotationMetadata;
|
||||||
import org.springframework.security.authorization.method.Jsr250AuthorizationManager;
|
|
||||||
import org.springframework.security.access.annotation.Secured;
|
import org.springframework.security.access.annotation.Secured;
|
||||||
import org.springframework.security.authorization.method.SecuredAuthorizationManager;
|
|
||||||
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
|
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
|
||||||
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
|
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
|
||||||
import org.springframework.security.authorization.method.AuthorizationMethodInterceptor;
|
import org.springframework.security.access.prepost.PostAuthorize;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.security.authorization.method.AuthorizationManagerMethodAfterAdvice;
|
import org.springframework.security.authorization.method.AuthorizationManagerMethodAfterAdvice;
|
||||||
import org.springframework.security.authorization.method.AuthorizationManagerMethodBeforeAdvice;
|
import org.springframework.security.authorization.method.AuthorizationManagerMethodBeforeAdvice;
|
||||||
import org.springframework.security.authorization.method.AuthorizationMethodAfterAdvice;
|
import org.springframework.security.authorization.method.AuthorizationMethodAfterAdvice;
|
||||||
import org.springframework.security.authorization.method.AuthorizationMethodBeforeAdvice;
|
import org.springframework.security.authorization.method.AuthorizationMethodBeforeAdvice;
|
||||||
|
import org.springframework.security.authorization.method.AuthorizationMethodInterceptor;
|
||||||
import org.springframework.security.authorization.method.DelegatingAuthorizationMethodAfterAdvice;
|
import org.springframework.security.authorization.method.DelegatingAuthorizationMethodAfterAdvice;
|
||||||
import org.springframework.security.authorization.method.DelegatingAuthorizationMethodBeforeAdvice;
|
import org.springframework.security.authorization.method.DelegatingAuthorizationMethodBeforeAdvice;
|
||||||
|
import org.springframework.security.authorization.method.Jsr250AuthorizationManager;
|
||||||
import org.springframework.security.authorization.method.MethodAuthorizationContext;
|
import org.springframework.security.authorization.method.MethodAuthorizationContext;
|
||||||
import org.springframework.security.access.prepost.PostAuthorize;
|
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
|
||||||
import org.springframework.security.authorization.method.PostAuthorizeAuthorizationManager;
|
import org.springframework.security.authorization.method.PostAuthorizeAuthorizationManager;
|
||||||
import org.springframework.security.authorization.method.PostFilterAuthorizationMethodAfterAdvice;
|
import org.springframework.security.authorization.method.PostFilterAuthorizationMethodAfterAdvice;
|
||||||
import org.springframework.security.authorization.method.PreAuthorizeAuthorizationManager;
|
import org.springframework.security.authorization.method.PreAuthorizeAuthorizationManager;
|
||||||
import org.springframework.security.authorization.method.PreFilterAuthorizationMethodBeforeAdvice;
|
import org.springframework.security.authorization.method.PreFilterAuthorizationMethodBeforeAdvice;
|
||||||
|
import org.springframework.security.authorization.method.SecuredAuthorizationManager;
|
||||||
import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base {@link Configuration} for enabling Spring Security Method Security.
|
* Base {@link Configuration} for enabling Spring Security Method Security.
|
||||||
|
@ -75,7 +77,7 @@ import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
||||||
*/
|
*/
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
final class MethodSecurityConfiguration implements ImportAware {
|
final class MethodSecurityConfiguration implements ImportAware, InitializingBean {
|
||||||
|
|
||||||
private MethodSecurityExpressionHandler methodSecurityExpressionHandler;
|
private MethodSecurityExpressionHandler methodSecurityExpressionHandler;
|
||||||
|
|
||||||
|
@ -214,6 +216,15 @@ final class MethodSecurityConfiguration implements ImportAware {
|
||||||
this.enableMethodSecurity = AnnotationAttributes.fromMap(attributes);
|
this.enableMethodSecurity = AnnotationAttributes.fromMap(attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
if (!securedEnabled() && !jsr250Enabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Assert.isNull(this.authorizationMethodBeforeAdvice,
|
||||||
|
"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() {
|
private boolean securedEnabled() {
|
||||||
return this.enableMethodSecurity.getBoolean("securedEnabled");
|
return this.enableMethodSecurity.getBoolean("securedEnabled");
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import org.junit.runner.RunWith;
|
||||||
|
|
||||||
import org.springframework.aop.MethodMatcher;
|
import org.springframework.aop.MethodMatcher;
|
||||||
import org.springframework.aop.support.JdkRegexpMethodPointcut;
|
import org.springframework.aop.support.JdkRegexpMethodPointcut;
|
||||||
|
import org.springframework.beans.factory.BeanCreationException;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.security.access.AccessDeniedException;
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
|
@ -35,12 +36,12 @@ import org.springframework.security.access.annotation.BusinessService;
|
||||||
import org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl;
|
import org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl;
|
||||||
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
|
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
|
||||||
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
|
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.AuthorizationManagerMethodBeforeAdvice;
|
import org.springframework.security.authorization.method.AuthorizationManagerMethodBeforeAdvice;
|
||||||
import org.springframework.security.authorization.method.AuthorizationMethodAfterAdvice;
|
import org.springframework.security.authorization.method.AuthorizationMethodAfterAdvice;
|
||||||
import org.springframework.security.authorization.method.AuthorizationMethodBeforeAdvice;
|
import org.springframework.security.authorization.method.AuthorizationMethodBeforeAdvice;
|
||||||
import org.springframework.security.authorization.method.MethodAuthorizationContext;
|
import org.springframework.security.authorization.method.MethodAuthorizationContext;
|
||||||
import org.springframework.security.authorization.AuthorizationDecision;
|
|
||||||
import org.springframework.security.authorization.AuthorizationManager;
|
|
||||||
import org.springframework.security.config.test.SpringTestRule;
|
import org.springframework.security.config.test.SpringTestRule;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners;
|
import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners;
|
||||||
|
@ -103,7 +104,7 @@ public class MethodSecurityConfigurationTests {
|
||||||
@WithMockUser
|
@WithMockUser
|
||||||
@Test
|
@Test
|
||||||
public void securedWhenRoleUserThenAccessDeniedException() {
|
public void securedWhenRoleUserThenAccessDeniedException() {
|
||||||
this.spring.register(MethodSecurityServiceConfig.class).autowire();
|
this.spring.register(MethodSecurityServiceEnabledConfig.class).autowire();
|
||||||
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.methodSecurityService::secured)
|
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.methodSecurityService::secured)
|
||||||
.withMessage("Access Denied");
|
.withMessage("Access Denied");
|
||||||
}
|
}
|
||||||
|
@ -119,7 +120,7 @@ public class MethodSecurityConfigurationTests {
|
||||||
@WithMockUser(roles = "ADMIN")
|
@WithMockUser(roles = "ADMIN")
|
||||||
@Test
|
@Test
|
||||||
public void securedUserWhenRoleAdminThenAccessDeniedException() {
|
public void securedUserWhenRoleAdminThenAccessDeniedException() {
|
||||||
this.spring.register(MethodSecurityServiceConfig.class).autowire();
|
this.spring.register(MethodSecurityServiceEnabledConfig.class).autowire();
|
||||||
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.methodSecurityService::securedUser)
|
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.methodSecurityService::securedUser)
|
||||||
.withMessage("Access Denied");
|
.withMessage("Access Denied");
|
||||||
}
|
}
|
||||||
|
@ -244,7 +245,7 @@ public class MethodSecurityConfigurationTests {
|
||||||
@WithMockUser(roles = "ADMIN")
|
@WithMockUser(roles = "ADMIN")
|
||||||
@Test
|
@Test
|
||||||
public void jsr250WhenRoleAdminThenAccessDeniedException() {
|
public void jsr250WhenRoleAdminThenAccessDeniedException() {
|
||||||
this.spring.register(MethodSecurityServiceConfig.class).autowire();
|
this.spring.register(MethodSecurityServiceEnabledConfig.class).autowire();
|
||||||
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.methodSecurityService::jsr250)
|
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.methodSecurityService::jsr250)
|
||||||
.withMessage("Access Denied");
|
.withMessage("Access Denied");
|
||||||
}
|
}
|
||||||
|
@ -252,7 +253,7 @@ public class MethodSecurityConfigurationTests {
|
||||||
@WithAnonymousUser
|
@WithAnonymousUser
|
||||||
@Test
|
@Test
|
||||||
public void jsr250PermitAllWhenRoleAnonymousThenPasses() {
|
public void jsr250PermitAllWhenRoleAnonymousThenPasses() {
|
||||||
this.spring.register(MethodSecurityServiceConfig.class).autowire();
|
this.spring.register(MethodSecurityServiceEnabledConfig.class).autowire();
|
||||||
String result = this.methodSecurityService.jsr250PermitAll();
|
String result = this.methodSecurityService.jsr250PermitAll();
|
||||||
assertThat(result).isNull();
|
assertThat(result).isNull();
|
||||||
}
|
}
|
||||||
|
@ -272,7 +273,14 @@ public class MethodSecurityConfigurationTests {
|
||||||
this.businessService.rolesAllowedUser();
|
this.businessService.rolesAllowedUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
@EnableMethodSecurity(securedEnabled = true, jsr250Enabled = true)
|
@Test
|
||||||
|
public void configureWhenCustomAdviceAndSecureEnabledThenException() {
|
||||||
|
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() -> this.spring
|
||||||
|
.register(CustomAuthorizationManagerBeforeAdviceConfig.class, MethodSecurityServiceEnabledConfig.class)
|
||||||
|
.autowire());
|
||||||
|
}
|
||||||
|
|
||||||
|
@EnableMethodSecurity
|
||||||
static class MethodSecurityServiceConfig {
|
static class MethodSecurityServiceConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@ -292,6 +300,16 @@ public class MethodSecurityConfigurationTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EnableMethodSecurity(securedEnabled = true, jsr250Enabled = true)
|
||||||
|
static class MethodSecurityServiceEnabledConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
MethodSecurityService methodSecurityService() {
|
||||||
|
return new MethodSecurityServiceImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@EnableMethodSecurity
|
@EnableMethodSecurity
|
||||||
static class CustomPermissionEvaluatorConfig {
|
static class CustomPermissionEvaluatorConfig {
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue