Document Reactive Method security requires Publisher return types

Fixes: gh-4988
This commit is contained in:
Rob Winch 2018-02-07 16:31:41 -06:00
parent ea3dd336aa
commit 964a14b224
5 changed files with 26 additions and 0 deletions

View File

@ -28,6 +28,12 @@ public class DelegatingReactiveMessageService implements ReactiveMessageService
this.delegate = delegate;
}
@Override
@PreAuthorize("denyAll")
public String notPublisherPreAuthorizeFindById(long id) {
return this.delegate.notPublisherPreAuthorizeFindById(id);
}
@Override
public Mono<String> monoFindById(long id) {
return delegate.monoFindById(id);

View File

@ -34,6 +34,7 @@ import reactor.test.StepVerifier;
import reactor.test.publisher.TestPublisher;
import reactor.util.context.Context;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.*;
/**
@ -60,6 +61,14 @@ public class EnableReactiveMethodSecurityTests {
this.delegate = config.delegate;
}
@Test
public void notPublisherPreAuthorizeFindByIdThenThrowsIllegalStateException() {
assertThatThrownBy(() -> this.messageService.notPublisherPreAuthorizeFindById(1L))
.isInstanceOf(IllegalStateException.class)
.extracting(Throwable::getMessage)
.contains("The returnType class java.lang.String on public abstract java.lang.String org.springframework.security.config.annotation.method.configuration.ReactiveMessageService.notPublisherPreAuthorizeFindById(long) must return an instance of org.reactivestreams.Publisher (i.e. Mono / Flux) in order to support Reactor Context");
}
@Test
public void monoWhenPermitAllThenAopDoesNotSubscribe() {
when(this.delegate.monoFindById(1L)).thenReturn(Mono.from(result));

View File

@ -20,6 +20,8 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public interface ReactiveMessageService {
String notPublisherPreAuthorizeFindById(long id);
Mono<String> monoFindById(long id);
Mono<String> monoPreAuthorizeHasRoleFindById(long id);
Mono<String> monoPostAuthorizeFindById(long id);

View File

@ -64,6 +64,9 @@ public class PrePostAdviceReactiveMethodInterceptor implements MethodInterceptor
throws Throwable {
Method method = invocation.getMethod();
Class<?> returnType = method.getReturnType();
if (!Publisher.class.isAssignableFrom(returnType)) {
throw new IllegalStateException("The returnType " + returnType + " on " + method + " must return an instance of org.reactivestreams.Publisher (i.e. Mono / Flux) in order to support Reactor Context");
}
Class<?> targetClass = invocation.getThis().getClass();
Collection<ConfigAttribute> attributes = this.attributeSource
.getAttributes(method, targetClass);

View File

@ -1718,6 +1718,12 @@ For additional information about methods that can be overridden, refer to the `G
Spring Security supports method security using https://projectreactor.io/docs/core/release/reference/#context[Reactor's Context] which is setup using `ReactiveSecurityContextHolder`.
For example, this demonstrates how to retrieve the currently logged in user's message.
[NOTE]
====
For this to work the return type of the method must be a `org.reactivestreams.Publisher` (i.e. `Mono`/`Flux`).
This is necessary to integrate with Reactor's `Context`.
====
[source,java]
----
Authentication authentication = new TestingAuthenticationToken("user", "password", "ROLE_USER");