Skip to content

Commit e990174

Browse files
committed
Polish ReactiveMethodSecurity Support
- Changed annotation property to useAuthorizationManager to match related XML support - Moved support found in bean post-processors back into interceptors directly. This reduces the number of components to maintain and simplifies ongoing support - Added @deprecated annotation to indicate that applications should use AuthorizationManagerBeforeReactiveMethodInterceptor and AuthorizationManagerAfterReactiveMethodInterceptor instead. While true that the new support does not support coroutines, the existing coroutine support is problematic since it cannot be reliably paired with other method interceptors - Moved expression handler configuration to the constructors - Constrain all method security interceptors to require publisher types - Use ReactiveAdapter to check for single-value types as well Issue gh-9401 Polish
1 parent 6fd23d2 commit e990174

File tree

30 files changed

+283
-412
lines changed

30 files changed

+283
-412
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,6 @@
7575
* used.
7676
* @since 5.8
7777
*/
78-
boolean authorizationManager() default false;
78+
boolean useAuthorizationManager() default false;
7979

8080
}

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

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,35 +45,31 @@ final class ReactiveAuthorizationManagerMethodSecurityConfiguration {
4545
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
4646
PreFilterAuthorizationReactiveMethodInterceptor preFilterInterceptor(
4747
MethodSecurityExpressionHandler expressionHandler) {
48-
PreFilterAuthorizationReactiveMethodInterceptor preFilter = new PreFilterAuthorizationReactiveMethodInterceptor();
49-
preFilter.setExpressionHandler(expressionHandler);
50-
return preFilter;
48+
return new PreFilterAuthorizationReactiveMethodInterceptor(expressionHandler);
5149
}
5250

5351
@Bean
5452
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
5553
AuthorizationManagerBeforeReactiveMethodInterceptor preAuthorizeInterceptor(
5654
MethodSecurityExpressionHandler expressionHandler) {
57-
PreAuthorizeReactiveAuthorizationManager authorizationManager = new PreAuthorizeReactiveAuthorizationManager();
58-
authorizationManager.setExpressionHandler(expressionHandler);
55+
PreAuthorizeReactiveAuthorizationManager authorizationManager = new PreAuthorizeReactiveAuthorizationManager(
56+
expressionHandler);
5957
return AuthorizationManagerBeforeReactiveMethodInterceptor.preAuthorize(authorizationManager);
6058
}
6159

6260
@Bean
6361
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
6462
PostFilterAuthorizationReactiveMethodInterceptor postFilterInterceptor(
6563
MethodSecurityExpressionHandler expressionHandler) {
66-
PostFilterAuthorizationReactiveMethodInterceptor postFilter = new PostFilterAuthorizationReactiveMethodInterceptor();
67-
postFilter.setExpressionHandler(expressionHandler);
68-
return postFilter;
64+
return new PostFilterAuthorizationReactiveMethodInterceptor(expressionHandler);
6965
}
7066

7167
@Bean
7268
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
7369
AuthorizationManagerAfterReactiveMethodInterceptor postAuthorizeInterceptor(
7470
MethodSecurityExpressionHandler expressionHandler) {
75-
PostAuthorizeReactiveAuthorizationManager authorizationManager = new PostAuthorizeReactiveAuthorizationManager();
76-
authorizationManager.setExpressionHandler(expressionHandler);
71+
PostAuthorizeReactiveAuthorizationManager authorizationManager = new PostAuthorizeReactiveAuthorizationManager(
72+
expressionHandler);
7773
return AuthorizationManagerAfterReactiveMethodInterceptor.postAuthorize(authorizationManager);
7874
}
7975

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public String[] selectImports(AnnotationMetadata importMetadata) {
4444
EnableReactiveMethodSecurity annotation = importMetadata.getAnnotations()
4545
.get(EnableReactiveMethodSecurity.class).synthesize();
4646
List<String> imports = new ArrayList<>(Arrays.asList(this.autoProxy.selectImports(importMetadata)));
47-
if (annotation.authorizationManager()) {
47+
if (annotation.useAuthorizationManager()) {
4848
imports.add(ReactiveAuthorizationManagerMethodSecurityConfiguration.class.getName());
4949
}
5050
else {

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ public Flux<String> fluxManyAnnotations(Flux<String> flux) {
112112
return flux;
113113
}
114114

115+
@PostFilter("filterObject.length > 5")
116+
public Flux<String> fluxPostFilter(Flux<String> flux) {
117+
return flux;
118+
}
119+
115120
@Override
116121
public Publisher<String> publisherFindById(long id) {
117122
return this.delegate.publisherFindById(id);

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

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242

4343
/**
4444
* Tests for {@link EnableReactiveMethodSecurity} with the
45-
* {@link EnableReactiveMethodSecurity#authorizationManager()} flag set to true.
45+
* {@link EnableReactiveMethodSecurity#useAuthorizationManager()} flag set to true.
4646
*
4747
* @author Evgeniy Cheban
4848
*/
@@ -79,8 +79,7 @@ public void notPublisherPreAuthorizeFindByIdThenThrowsIllegalStateException() {
7979
.withMessage("The returnType class java.lang.String on public abstract java.lang.String "
8080
+ "org.springframework.security.config.annotation.method.configuration.ReactiveMessageService"
8181
+ ".notPublisherPreAuthorizeFindById(long) must return an instance of org.reactivestreams"
82-
+ ".Publisher (i.e. Mono / Flux) or the function must be a Kotlin coroutine "
83-
+ "function in order to support Reactor Context");
82+
+ ".Publisher (for example, a Mono or Flux) in order to support Reactor Context");
8483
}
8584

8685
@Test
@@ -340,6 +339,13 @@ public void fluxManyAnnotationsWhenNameNotAllowedThenFails() {
340339
StepVerifier.create(flux).expectNext("harold", "jonathan").expectError(AccessDeniedException.class).verify();
341340
}
342341

342+
@Test
343+
public void fluxPostFilterWhenFilteringThenWorks() {
344+
Flux<String> flux = this.messageService.fluxPostFilter(Flux.just("harold", "jonathan", "michael", "pete", "bo"))
345+
.contextWrite(this.withAdmin);
346+
StepVerifier.create(flux).expectNext("harold", "jonathan", "michael").verifyComplete();
347+
}
348+
343349
// Publisher tests
344350
@Test
345351
public void publisherWhenPermitAllThenAopDoesNotSubscribe() {
@@ -458,7 +464,7 @@ static <T> Publisher<T> publisherJust(T... data) {
458464
return publisher(Flux.just(data));
459465
}
460466

461-
@EnableReactiveMethodSecurity(authorizationManager = true)
467+
@EnableReactiveMethodSecurity(useAuthorizationManager = true)
462468
static class Config {
463469

464470
ReactiveMessageService delegate = mock(ReactiveMessageService.class);

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ public interface ReactiveMessageService {
4848

4949
Flux<String> fluxManyAnnotations(Flux<String> flux);
5050

51+
Flux<String> fluxPostFilter(Flux<String> flux);
52+
5153
Publisher<String> publisherFindById(long id);
5254

5355
Publisher<String> publisherPreAuthorizeHasRoleFindById(long id);

core/src/main/java/org/springframework/security/access/prepost/PrePostAdviceReactiveMethodInterceptor.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,12 @@
5252
* @author Rob Winch
5353
* @author Eleftheria Stein
5454
* @since 5.0
55+
* @deprecated Use
56+
* {@link org.springframework.security.authorization.method.AuthorizationManagerBeforeReactiveMethodInterceptor}
57+
* or
58+
* {@link org.springframework.security.authorization.method.AuthorizationManagerAfterReactiveMethodInterceptor}
5559
*/
60+
@Deprecated
5661
public class PrePostAdviceReactiveMethodInterceptor implements MethodInterceptor {
5762

5863
private Authentication anonymous = new AnonymousAuthenticationToken("key", "anonymous",

core/src/main/java/org/springframework/security/authorization/method/AuthorizationAfterReactiveMethodInterceptor.java

Lines changed: 0 additions & 76 deletions
This file was deleted.

core/src/main/java/org/springframework/security/authorization/method/AuthorizationBeanFactoryPostProcessor.java

Lines changed: 0 additions & 59 deletions
This file was deleted.

core/src/main/java/org/springframework/security/authorization/method/AuthorizationBeforeReactiveMethodInterceptor.java

Lines changed: 0 additions & 82 deletions
This file was deleted.

0 commit comments

Comments
 (0)