Improve reactive support for access to Principal

The method to access the Principal from the ServerWebExchange is now
a Mono<Principal> (rather than Optional<Principal>).

There is also support for Principal as a controller method argument.

Issue: SPR-14680, SPR-14865
This commit is contained in:
Rossen Stoyanchev 2016-11-01 18:32:56 +02:00
parent e1a382b61f
commit 99cacaa72d
7 changed files with 77 additions and 21 deletions

View File

@ -0,0 +1,56 @@
/*
* Copyright 2002-2016 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
*
* http://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.web.reactive.result.method.annotation;
import java.security.Principal;
import reactor.core.publisher.Mono;
import org.springframework.core.MethodParameter;
import org.springframework.web.reactive.result.method.BindingContext;
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver;
import org.springframework.web.server.ServerWebExchange;
/**
* Resolves method argument value of type {@link java.security.Principal}.
*
* @author Rossen Stoyanchev
* @since 5.0
* @see ServerWebExchangeArgumentResolver
*/
public class PrincipalArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return (Principal.class.isAssignableFrom(parameter.getParameterType()));
}
@Override
public Mono<Object> resolveArgument(MethodParameter parameter, BindingContext context,
ServerWebExchange exchange) {
Class<?> paramType = parameter.getParameterType();
if (Principal.class.isAssignableFrom(paramType)) {
return exchange.getPrincipal().cast(Object.class);
}
else {
// should never happen...
throw new IllegalArgumentException(
"Unknown parameter type: " + paramType + " in method: " + parameter.getMethod());
}
}
}

View File

@ -241,6 +241,7 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, BeanFactory
resolvers.add(new HttpEntityArgumentResolver(getMessageReaders(), getReactiveAdapterRegistry()));
resolvers.add(new ModelArgumentResolver());
resolvers.add(new ServerWebExchangeArgumentResolver());
resolvers.add(new PrincipalArgumentResolver());
resolvers.add(new WebSessionArgumentResolver());
// Custom resolvers

View File

@ -30,15 +30,17 @@ import org.springframework.web.server.ServerWebExchange;
* <ul>
* <li>{@link ServerWebExchange}
* <li>{@link ServerHttpRequest}
* <li>{@link HttpMethod}
* <li>{@link ServerHttpResponse}
* <li>{@link HttpMethod}
* </ul>
*
* <p>For the {@code WebSession} see {@link WebSessionArgumentResolver}.
* <p>For the {@code WebSession} see {@link WebSessionArgumentResolver}
* and for the {@code Principal} see {@link PrincipalArgumentResolver}.
*
* @author Rossen Stoyanchev
* @since 5.0
* @see WebSessionArgumentResolver
* @see PrincipalArgumentResolver
*/
public class ServerWebExchangeArgumentResolver implements SyncHandlerMethodArgumentResolver {
@ -56,25 +58,23 @@ public class ServerWebExchangeArgumentResolver implements SyncHandlerMethodArgum
ServerWebExchange exchange) {
Class<?> paramType = parameter.getParameterType();
Object value;
if (ServerWebExchange.class.isAssignableFrom(paramType)) {
value = exchange;
return Optional.of(exchange);
}
else if (ServerHttpRequest.class.isAssignableFrom(paramType)) {
value = exchange.getRequest();
return Optional.of(exchange.getRequest());
}
else if (ServerHttpResponse.class.isAssignableFrom(paramType)) {
value = exchange.getResponse();
return Optional.of(exchange.getResponse());
}
else if (HttpMethod.class == paramType) {
value = exchange.getRequest().getMethod();
return Optional.of(exchange.getRequest().getMethod());
}
else {
// should never happen...
throw new IllegalArgumentException(
"Unknown parameter type: " + paramType + " in method: " + parameter.getMethod());
}
return Optional.of(value);
}
}

View File

@ -16,7 +16,6 @@
package org.springframework.web.server;
import java.security.Principal;
import java.util.Optional;
import reactor.core.publisher.Mono;
@ -40,7 +39,7 @@ class DefaultServerWebExchangeMutativeBuilder implements ServerWebExchange.Mutat
private ServerHttpResponse response;
private Principal user;
private Mono<Principal> user;
private Mono<WebSession> session;
@ -66,7 +65,7 @@ class DefaultServerWebExchangeMutativeBuilder implements ServerWebExchange.Mutat
}
@Override
public ServerWebExchange.MutativeBuilder setPrincipal(Principal user) {
public ServerWebExchange.MutativeBuilder setPrincipal(Mono<Principal> user) {
this.user = user;
return this;
}
@ -100,7 +99,7 @@ class DefaultServerWebExchangeMutativeBuilder implements ServerWebExchange.Mutat
private final ServerHttpResponse response;
private final Principal user;
private final Mono<Principal> userMono;
private final Mono<WebSession> session;
@ -108,13 +107,13 @@ class DefaultServerWebExchangeMutativeBuilder implements ServerWebExchange.Mutat
public MutativeDecorator(ServerWebExchange delegate,
ServerHttpRequest request, ServerHttpResponse response, Principal user,
ServerHttpRequest request, ServerHttpResponse response, Mono<Principal> user,
Mono<WebSession> session, Mono<MultiValueMap<String, String>> formData) {
super(delegate);
this.request = request;
this.response = response;
this.user = user;
this.userMono = user;
this.session = session;
this.formData = formData;
}
@ -137,8 +136,8 @@ class DefaultServerWebExchangeMutativeBuilder implements ServerWebExchange.Mutat
@SuppressWarnings("unchecked")
@Override
public <T extends Principal> Optional<T> getPrincipal() {
return (this.user != null ? Optional.of((T) this.user) : getDelegate().getPrincipal());
public <T extends Principal> Mono<T> getPrincipal() {
return (this.userMono != null ? (Mono<T>) this.userMono : getDelegate().getPrincipal());
}
@Override

View File

@ -73,7 +73,7 @@ public interface ServerWebExchange {
/**
* Return the authenticated user for the request, if any.
*/
<T extends Principal> Optional<T> getPrincipal();
<T extends Principal> Mono<T> getPrincipal();
/**
* Return the form data from the body of the request or an empty {@code Mono}
@ -155,7 +155,7 @@ public interface ServerWebExchange {
/**
* Set the principal to use.
*/
MutativeBuilder setPrincipal(Principal user);
MutativeBuilder setPrincipal(Mono<Principal> user);
/**
* Set the session to use.

View File

@ -84,7 +84,7 @@ public class ServerWebExchangeDecorator implements ServerWebExchange {
}
@Override
public <T extends Principal> Optional<T> getPrincipal() {
public <T extends Principal> Mono<T> getPrincipal() {
return getDelegate().getPrincipal();
}

View File

@ -135,8 +135,8 @@ public class DefaultServerWebExchange implements ServerWebExchange {
}
@Override
public <T extends Principal> Optional<T> getPrincipal() {
return Optional.empty();
public <T extends Principal> Mono<T> getPrincipal() {
return Mono.empty();
}
@Override