Skip to content

Commit 68cf744

Browse files
committed
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
1 parent 45376b3 commit 68cf744

File tree

2 files changed

+42
-13
lines changed

2 files changed

+42
-13
lines changed

config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityConfiguration.java

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.springframework.aop.support.DefaultPointcutAdvisor;
3737
import org.springframework.aop.support.Pointcuts;
3838
import org.springframework.aop.support.StaticMethodMatcher;
39+
import org.springframework.beans.factory.InitializingBean;
3940
import org.springframework.beans.factory.annotation.Autowired;
4041
import org.springframework.beans.factory.config.BeanDefinition;
4142
import org.springframework.context.annotation.Bean;
@@ -45,26 +46,27 @@
4546
import org.springframework.core.annotation.AnnotatedElementUtils;
4647
import org.springframework.core.annotation.AnnotationAttributes;
4748
import org.springframework.core.type.AnnotationMetadata;
48-
import org.springframework.security.authorization.method.Jsr250AuthorizationManager;
4949
import org.springframework.security.access.annotation.Secured;
50-
import org.springframework.security.authorization.method.SecuredAuthorizationManager;
5150
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
5251
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
53-
import org.springframework.security.authorization.method.AuthorizationMethodInterceptor;
52+
import org.springframework.security.access.prepost.PostAuthorize;
53+
import org.springframework.security.access.prepost.PreAuthorize;
5454
import org.springframework.security.authorization.method.AuthorizationManagerMethodAfterAdvice;
5555
import org.springframework.security.authorization.method.AuthorizationManagerMethodBeforeAdvice;
5656
import org.springframework.security.authorization.method.AuthorizationMethodAfterAdvice;
5757
import org.springframework.security.authorization.method.AuthorizationMethodBeforeAdvice;
58+
import org.springframework.security.authorization.method.AuthorizationMethodInterceptor;
5859
import org.springframework.security.authorization.method.DelegatingAuthorizationMethodAfterAdvice;
5960
import org.springframework.security.authorization.method.DelegatingAuthorizationMethodBeforeAdvice;
61+
import org.springframework.security.authorization.method.Jsr250AuthorizationManager;
6062
import org.springframework.security.authorization.method.MethodAuthorizationContext;
61-
import org.springframework.security.access.prepost.PostAuthorize;
62-
import org.springframework.security.access.prepost.PreAuthorize;
6363
import org.springframework.security.authorization.method.PostAuthorizeAuthorizationManager;
6464
import org.springframework.security.authorization.method.PostFilterAuthorizationMethodAfterAdvice;
6565
import org.springframework.security.authorization.method.PreAuthorizeAuthorizationManager;
6666
import org.springframework.security.authorization.method.PreFilterAuthorizationMethodBeforeAdvice;
67+
import org.springframework.security.authorization.method.SecuredAuthorizationManager;
6768
import org.springframework.security.config.core.GrantedAuthorityDefaults;
69+
import org.springframework.util.Assert;
6870

6971
/**
7072
* Base {@link Configuration} for enabling Spring Security Method Security.
@@ -75,7 +77,7 @@
7577
*/
7678
@Configuration(proxyBeanMethods = false)
7779
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
78-
final class MethodSecurityConfiguration implements ImportAware {
80+
final class MethodSecurityConfiguration implements ImportAware, InitializingBean {
7981

8082
private MethodSecurityExpressionHandler methodSecurityExpressionHandler;
8183

@@ -214,6 +216,15 @@ public void setImportMetadata(AnnotationMetadata importMetadata) {
214216
this.enableMethodSecurity = AnnotationAttributes.fromMap(attributes);
215217
}
216218

219+
@Override
220+
public void afterPropertiesSet() throws Exception {
221+
if (!securedEnabled() && !jsr250Enabled()) {
222+
return;
223+
}
224+
Assert.isNull(this.authorizationMethodBeforeAdvice,
225+
"You have specified your own advice, meaning that the annotation attributes securedEnabled and jsr250Enabled will be ignored. Please choose one or the other.");
226+
}
227+
217228
private boolean securedEnabled() {
218229
return this.enableMethodSecurity.getBoolean("securedEnabled");
219230
}

config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityConfigurationTests.java

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import org.springframework.aop.MethodMatcher;
2929
import org.springframework.aop.support.JdkRegexpMethodPointcut;
30+
import org.springframework.beans.factory.BeanCreationException;
3031
import org.springframework.beans.factory.annotation.Autowired;
3132
import org.springframework.context.annotation.Bean;
3233
import org.springframework.security.access.AccessDeniedException;
@@ -35,12 +36,12 @@
3536
import org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl;
3637
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
3738
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
39+
import org.springframework.security.authorization.AuthorizationDecision;
40+
import org.springframework.security.authorization.AuthorizationManager;
3841
import org.springframework.security.authorization.method.AuthorizationManagerMethodBeforeAdvice;
3942
import org.springframework.security.authorization.method.AuthorizationMethodAfterAdvice;
4043
import org.springframework.security.authorization.method.AuthorizationMethodBeforeAdvice;
4144
import org.springframework.security.authorization.method.MethodAuthorizationContext;
42-
import org.springframework.security.authorization.AuthorizationDecision;
43-
import org.springframework.security.authorization.AuthorizationManager;
4445
import org.springframework.security.config.test.SpringTestRule;
4546
import org.springframework.security.core.Authentication;
4647
import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners;
@@ -103,7 +104,7 @@ public void preAuthorizeNotAnonymousWhenRoleUserThenPasses() {
103104
@WithMockUser
104105
@Test
105106
public void securedWhenRoleUserThenAccessDeniedException() {
106-
this.spring.register(MethodSecurityServiceConfig.class).autowire();
107+
this.spring.register(MethodSecurityServiceEnabledConfig.class).autowire();
107108
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.methodSecurityService::secured)
108109
.withMessage("Access Denied");
109110
}
@@ -119,7 +120,7 @@ public void securedWhenRoleAdminThenPasses() {
119120
@WithMockUser(roles = "ADMIN")
120121
@Test
121122
public void securedUserWhenRoleAdminThenAccessDeniedException() {
122-
this.spring.register(MethodSecurityServiceConfig.class).autowire();
123+
this.spring.register(MethodSecurityServiceEnabledConfig.class).autowire();
123124
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.methodSecurityService::securedUser)
124125
.withMessage("Access Denied");
125126
}
@@ -244,15 +245,15 @@ public void securedUserWhenCustomAfterAdviceConfiguredAndNameNotBobThenAccessDen
244245
@WithMockUser(roles = "ADMIN")
245246
@Test
246247
public void jsr250WhenRoleAdminThenAccessDeniedException() {
247-
this.spring.register(MethodSecurityServiceConfig.class).autowire();
248+
this.spring.register(MethodSecurityServiceEnabledConfig.class).autowire();
248249
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.methodSecurityService::jsr250)
249250
.withMessage("Access Denied");
250251
}
251252

252253
@WithAnonymousUser
253254
@Test
254255
public void jsr250PermitAllWhenRoleAnonymousThenPasses() {
255-
this.spring.register(MethodSecurityServiceConfig.class).autowire();
256+
this.spring.register(MethodSecurityServiceEnabledConfig.class).autowire();
256257
String result = this.methodSecurityService.jsr250PermitAll();
257258
assertThat(result).isNull();
258259
}
@@ -272,7 +273,14 @@ public void rolesAllowedUserWhenRoleUserThenPasses() {
272273
this.businessService.rolesAllowedUser();
273274
}
274275

275-
@EnableMethodSecurity(securedEnabled = true, jsr250Enabled = true)
276+
@Test
277+
public void configureWhenCustomAdviceAndSecureEnabledThenException() {
278+
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() -> this.spring
279+
.register(CustomAuthorizationManagerBeforeAdviceConfig.class, MethodSecurityServiceEnabledConfig.class)
280+
.autowire());
281+
}
282+
283+
@EnableMethodSecurity
276284
static class MethodSecurityServiceConfig {
277285

278286
@Bean
@@ -292,6 +300,16 @@ BusinessService businessService() {
292300

293301
}
294302

303+
@EnableMethodSecurity(securedEnabled = true, jsr250Enabled = true)
304+
static class MethodSecurityServiceEnabledConfig {
305+
306+
@Bean
307+
MethodSecurityService methodSecurityService() {
308+
return new MethodSecurityServiceImpl();
309+
}
310+
311+
}
312+
295313
@EnableMethodSecurity
296314
static class CustomPermissionEvaluatorConfig {
297315

0 commit comments

Comments
 (0)