1
0
mirror of synced 2026-05-22 13:23:17 +00:00

Reformat code using spring-javaformat

Run `./gradlew format` to reformat all java files.

Issue gh-8945
This commit is contained in:
Phillip Webb
2020-08-10 16:39:17 -05:00
committed by Rob Winch
parent 81d9c6cac5
commit b7fc18262d
2487 changed files with 41506 additions and 46548 deletions
@@ -26,6 +26,7 @@ import org.springframework.util.MimeType;
* @since 5.2
*/
public interface PayloadExchange {
PayloadExchangeType getType();
Payload getPayload();
@@ -33,4 +34,5 @@ public interface PayloadExchange {
MimeType getDataMimeType();
MimeType getMetadataMimeType();
}
@@ -23,14 +23,16 @@ package org.springframework.security.rsocket.api;
* @since 5.2
*/
public enum PayloadExchangeType {
/**
* The <a href="https://rsocket.io/docs/Protocol#setup-frame-0x01">Setup</a>. Can
* be used to determine if a Payload is part of the connection
* The <a href="https://rsocket.io/docs/Protocol#setup-frame-0x01">Setup</a>. Can be
* used to determine if a Payload is part of the connection
*/
SETUP(false),
/**
* A <a href="https://rsocket.io/docs/Protocol#frame-fnf">Fire and Forget</a> exchange.
* A <a href="https://rsocket.io/docs/Protocol#frame-fnf">Fire and Forget</a>
* exchange.
*/
FIRE_AND_FORGET(true),
@@ -41,9 +43,9 @@ public enum PayloadExchangeType {
REQUEST_RESPONSE(true),
/**
* A <a href="https://rsocket.io/docs/Protocol#request-stream-frame">Request Stream</a>
* exchange. This is only represents the request portion. The {@link #PAYLOAD} type
* represents the data that submitted.
* A <a href="https://rsocket.io/docs/Protocol#request-stream-frame">Request
* Stream</a> exchange. This is only represents the request portion. The
* {@link #PAYLOAD} type represents the data that submitted.
*/
REQUEST_STREAM(true),
@@ -77,4 +79,5 @@ public enum PayloadExchangeType {
public boolean isRequest() {
return this.isRequest;
}
}
@@ -19,14 +19,15 @@ package org.springframework.security.rsocket.api;
import reactor.core.publisher.Mono;
/**
* Contract for interception-style, chained processing of Payloads that may
* be used to implement cross-cutting, application-agnostic requirements such
* as security, timeouts, and others.
* Contract for interception-style, chained processing of Payloads that may be used to
* implement cross-cutting, application-agnostic requirements such as security, timeouts,
* and others.
*
* @author Rob Winch
* @since 5.2
*/
public interface PayloadInterceptor {
/**
* Process the Web request and (optionally) delegate to the next
* {@code PayloadInterceptor} through the given {@link PayloadInterceptorChain}.
@@ -35,4 +36,5 @@ public interface PayloadInterceptor {
* @return {@code Mono<Void>} to indicate when payload processing is complete
*/
Mono<Void> intercept(PayloadExchange exchange, PayloadInterceptorChain chain);
}
@@ -19,16 +19,18 @@ package org.springframework.security.rsocket.api;
import reactor.core.publisher.Mono;
/**
* Contract to allow a {@link PayloadInterceptor} to delegate to the next in the chain.
* *
* Contract to allow a {@link PayloadInterceptor} to delegate to the next in the chain. *
*
* @author Rob Winch
* @since 5.2
*/
public interface PayloadInterceptorChain {
/**
* Process the payload exchange.
* @param exchange the current server exchange
* @return {@code Mono<Void>} to indicate when request processing is complete
*/
Mono<Void> next(PayloadExchange exchange);
}
@@ -39,7 +39,9 @@ import java.util.List;
public class AnonymousPayloadInterceptor implements PayloadInterceptor, Ordered {
private String key;
private Object principal;
private List<GrantedAuthority> authorities;
private int order;
@@ -47,7 +49,6 @@ public class AnonymousPayloadInterceptor implements PayloadInterceptor, Ordered
/**
* Creates a filter with a principal named "anonymousUser" and the single authority
* "ROLE_ANONYMOUS".
*
* @param key the key to identify tokens created by this filter
*/
public AnonymousPayloadInterceptor(String key) {
@@ -55,12 +56,11 @@ public class AnonymousPayloadInterceptor implements PayloadInterceptor, Ordered
}
/**
* @param key key the key to identify tokens created by this filter
* @param principal the principal which will be used to represent anonymous users
* @param key key the key to identify tokens created by this filter
* @param principal the principal which will be used to represent anonymous users
* @param authorities the authority list for anonymous users
*/
public AnonymousPayloadInterceptor(String key, Object principal,
List<GrantedAuthority> authorities) {
public AnonymousPayloadInterceptor(String key, Object principal, List<GrantedAuthority> authorities) {
Assert.hasLength(key, "key cannot be null or empty");
Assert.notNull(principal, "Anonymous authentication principal must be set");
Assert.notNull(authorities, "Anonymous authorities must be set");
@@ -80,14 +80,13 @@ public class AnonymousPayloadInterceptor implements PayloadInterceptor, Ordered
@Override
public Mono<Void> intercept(PayloadExchange exchange, PayloadInterceptorChain chain) {
return ReactiveSecurityContextHolder.getContext()
.switchIfEmpty(Mono.defer(() -> {
AnonymousAuthenticationToken authentication = new AnonymousAuthenticationToken(
this.key, this.principal, this.authorities);
return chain.next(exchange)
.subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication))
.then(Mono.empty());
}))
.flatMap(securityContext -> chain.next(exchange));
return ReactiveSecurityContextHolder.getContext().switchIfEmpty(Mono.defer(() -> {
AnonymousAuthenticationToken authentication = new AnonymousAuthenticationToken(this.key, this.principal,
this.authorities);
return chain.next(exchange)
.subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication))
.then(Mono.empty());
})).flatMap(securityContext -> chain.next(exchange));
}
}
@@ -36,29 +36,32 @@ import java.nio.charset.StandardCharsets;
import java.util.Map;
/**
* Converts from the {@link PayloadExchange} for
* <a href="https://github.com/rsocket/rsocket/blob/5920ed374d008abb712cb1fd7c9d91778b2f4a68/Extensions/Security/Authentication.md">Authentication Extension</a>.
* For
* <a href="https://github.com/rsocket/rsocket/blob/5920ed374d008abb712cb1fd7c9d91778b2f4a68/Extensions/Security/Simple.md">Simple</a>
* a {@link UsernamePasswordAuthenticationToken} is returned. For
* <a href="https://github.com/rsocket/rsocket/blob/5920ed374d008abb712cb1fd7c9d91778b2f4a68/Extensions/Security/Bearer.md">Bearer</a>
* Converts from the {@link PayloadExchange} for <a href=
* "https://github.com/rsocket/rsocket/blob/5920ed374d008abb712cb1fd7c9d91778b2f4a68/Extensions/Security/Authentication.md">Authentication
* Extension</a>. For <a href=
* "https://github.com/rsocket/rsocket/blob/5920ed374d008abb712cb1fd7c9d91778b2f4a68/Extensions/Security/Simple.md">Simple</a>
* a {@link UsernamePasswordAuthenticationToken} is returned. For <a href=
* "https://github.com/rsocket/rsocket/blob/5920ed374d008abb712cb1fd7c9d91778b2f4a68/Extensions/Security/Bearer.md">Bearer</a>
* a {@link BearerTokenAuthenticationToken} is returned.
*
* @author Rob Winch
* @since 5.3
*/
public class AuthenticationPayloadExchangeConverter implements PayloadExchangeAuthenticationConverter {
private static final MimeType COMPOSITE_METADATA_MIME_TYPE = MimeTypeUtils.parseMimeType(
WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
private static final MimeType AUTHENTICATION_MIME_TYPE = MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_AUTHENTICATION.getString());
private static final MimeType COMPOSITE_METADATA_MIME_TYPE = MimeTypeUtils
.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
private static final MimeType AUTHENTICATION_MIME_TYPE = MimeTypeUtils
.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_AUTHENTICATION.getString());
private MetadataExtractor metadataExtractor = createDefaultExtractor();
@Override
public Mono<Authentication> convert(PayloadExchange exchange) {
return Mono.fromCallable(() -> this.metadataExtractor
.extract(exchange.getPayload(), this.COMPOSITE_METADATA_MIME_TYPE))
return Mono
.fromCallable(
() -> this.metadataExtractor.extract(exchange.getPayload(), this.COMPOSITE_METADATA_MIME_TYPE))
.flatMap(metadata -> Mono.justOrEmpty(authentication(metadata)));
}
@@ -74,7 +77,8 @@ public class AuthenticationPayloadExchangeConverter implements PayloadExchangeAu
WellKnownAuthType wellKnownAuthType = AuthMetadataCodec.readWellKnownAuthType(rawAuthentication);
if (WellKnownAuthType.SIMPLE.equals(wellKnownAuthType)) {
return simple(rawAuthentication);
} else if (WellKnownAuthType.BEARER.equals(wellKnownAuthType)) {
}
else if (WellKnownAuthType.BEARER.equals(wellKnownAuthType)) {
return bearer(rawAuthentication);
}
throw new IllegalArgumentException("Unknown Mime Type " + wellKnownAuthType);
@@ -99,4 +103,5 @@ public class AuthenticationPayloadExchangeConverter implements PayloadExchangeAu
result.metadataToExtract(AUTHENTICATION_MIME_TYPE, byte[].class, "authentication");
return result;
}
}
@@ -40,8 +40,7 @@ public class AuthenticationPayloadInterceptor implements PayloadInterceptor, Ord
private int order;
private PayloadExchangeAuthenticationConverter authenticationConverter =
new BasicAuthenticationPayloadExchangeConverter();
private PayloadExchangeAuthenticationConverter authenticationConverter = new BasicAuthenticationPayloadExchangeConverter();
/**
* Creates a new instance
@@ -65,22 +64,19 @@ public class AuthenticationPayloadInterceptor implements PayloadInterceptor, Ord
* Sets the convert to be used
* @param authenticationConverter
*/
public void setAuthenticationConverter(
PayloadExchangeAuthenticationConverter authenticationConverter) {
public void setAuthenticationConverter(PayloadExchangeAuthenticationConverter authenticationConverter) {
Assert.notNull(authenticationConverter, "authenticationConverter cannot be null");
this.authenticationConverter = authenticationConverter;
}
public Mono<Void> intercept(PayloadExchange exchange, PayloadInterceptorChain chain) {
return this.authenticationConverter.convert(exchange)
.switchIfEmpty(chain.next(exchange).then(Mono.empty()))
.flatMap(a -> this.authenticationManager.authenticate(a))
.flatMap(a -> onAuthenticationSuccess(chain.next(exchange), a));
return this.authenticationConverter.convert(exchange).switchIfEmpty(chain.next(exchange).then(Mono.empty()))
.flatMap(a -> this.authenticationManager.authenticate(a))
.flatMap(a -> onAuthenticationSuccess(chain.next(exchange), a));
}
private Mono<Void> onAuthenticationSuccess(Mono<Void> payload, Authentication authentication) {
return payload
.subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication));
return payload.subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication));
}
}
@@ -38,23 +38,26 @@ import reactor.core.publisher.Mono;
*/
public class BasicAuthenticationPayloadExchangeConverter implements PayloadExchangeAuthenticationConverter {
private MimeType metadataMimetype = MimeTypeUtils.parseMimeType(
WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
private MimeType metadataMimetype = MimeTypeUtils
.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
private MetadataExtractor metadataExtractor = createDefaultExtractor();
@Override
public Mono<Authentication> convert(PayloadExchange exchange) {
return Mono.fromCallable(() -> this.metadataExtractor
.extract(exchange.getPayload(), this.metadataMimetype))
.flatMap(metadata -> Mono.justOrEmpty(metadata.get(UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE.toString())))
return Mono.fromCallable(() -> this.metadataExtractor.extract(exchange.getPayload(), this.metadataMimetype))
.flatMap(metadata -> Mono
.justOrEmpty(metadata.get(UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE.toString())))
.cast(UsernamePasswordMetadata.class)
.map(credentials -> new UsernamePasswordAuthenticationToken(credentials.getUsername(), credentials.getPassword()));
.map(credentials -> new UsernamePasswordAuthenticationToken(credentials.getUsername(),
credentials.getPassword()));
}
private static MetadataExtractor createDefaultExtractor() {
DefaultMetadataExtractor result = new DefaultMetadataExtractor(new BasicAuthenticationDecoder());
result.metadataToExtract(UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE, UsernamePasswordMetadata.class, (String) null);
result.metadataToExtract(UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE,
UsernamePasswordMetadata.class, (String) null);
return result;
}
}
@@ -27,16 +27,16 @@ import reactor.core.publisher.Mono;
import java.nio.charset.StandardCharsets;
/**
* Converts from the {@link PayloadExchange} to a
* {@link BearerTokenAuthenticationToken} by extracting
* {@link BearerTokenMetadata#BEARER_AUTHENTICATION_MIME_TYPE} from the metadata.
* @author Rob Winch
* Converts from the {@link PayloadExchange} to a {@link BearerTokenAuthenticationToken}
* by extracting {@link BearerTokenMetadata#BEARER_AUTHENTICATION_MIME_TYPE} from the
* metadata.
*
* @author Rob Winch
* @since 5.2
*/
public class BearerPayloadExchangeConverter implements PayloadExchangeAuthenticationConverter {
private static final String BEARER_MIME_TYPE_VALUE =
BearerTokenMetadata.BEARER_AUTHENTICATION_MIME_TYPE.toString();
private static final String BEARER_MIME_TYPE_VALUE = BearerTokenMetadata.BEARER_AUTHENTICATION_MIME_TYPE.toString();
@Override
public Mono<Authentication> convert(PayloadExchange exchange) {
@@ -51,4 +51,5 @@ public class BearerPayloadExchangeConverter implements PayloadExchangeAuthentica
}
return Mono.empty();
}
}
@@ -22,9 +22,12 @@ import reactor.core.publisher.Mono;
/**
* Converts from a {@link PayloadExchange} to an {@link Authentication}
*
* @author Rob Winch
* @since 5.2
*/
public interface PayloadExchangeAuthenticationConverter {
Mono<Authentication> convert(PayloadExchange exchange);
}
@@ -34,12 +34,12 @@ import org.springframework.security.rsocket.api.PayloadInterceptor;
* @since 5.2
*/
public class AuthorizationPayloadInterceptor implements PayloadInterceptor, Ordered {
private final ReactiveAuthorizationManager<PayloadExchange> authorizationManager;
private int order;
public AuthorizationPayloadInterceptor(
ReactiveAuthorizationManager<PayloadExchange> authorizationManager) {
public AuthorizationPayloadInterceptor(ReactiveAuthorizationManager<PayloadExchange> authorizationManager) {
Assert.notNull(authorizationManager, "authorizationManager cannot be null");
this.authorizationManager = authorizationManager;
}
@@ -55,11 +55,12 @@ public class AuthorizationPayloadInterceptor implements PayloadInterceptor, Orde
@Override
public Mono<Void> intercept(PayloadExchange exchange, PayloadInterceptorChain chain) {
return ReactiveSecurityContextHolder.getContext()
.filter(c -> c.getAuthentication() != null)
return ReactiveSecurityContextHolder.getContext().filter(c -> c.getAuthentication() != null)
.map(SecurityContext::getAuthentication)
.switchIfEmpty(Mono.error(() -> new AuthenticationCredentialsNotFoundException("An Authentication (possibly AnonymousAuthenticationToken) is required.")))
.switchIfEmpty(Mono.error(() -> new AuthenticationCredentialsNotFoundException(
"An Authentication (possibly AnonymousAuthenticationToken) is required.")))
.as(authentication -> this.authorizationManager.verify(authentication, exchange))
.then(chain.next(exchange));
}
}
@@ -32,15 +32,18 @@ import java.util.List;
/**
* Maps a @{code List} of {@link PayloadExchangeMatcher} instances to
* @{code ReactiveAuthorizationManager} instances.
*
* @{code ReactiveAuthorizationManager} instances.
* @author Rob Winch
* @since 5.2
*/
public class PayloadExchangeMatcherReactiveAuthorizationManager implements ReactiveAuthorizationManager<PayloadExchange> {
public class PayloadExchangeMatcherReactiveAuthorizationManager
implements ReactiveAuthorizationManager<PayloadExchange> {
private final List<PayloadExchangeMatcherEntry<ReactiveAuthorizationManager<PayloadExchangeAuthorizationContext>>> mappings;
private PayloadExchangeMatcherReactiveAuthorizationManager(List<PayloadExchangeMatcherEntry<ReactiveAuthorizationManager<PayloadExchangeAuthorizationContext>>> mappings) {
private PayloadExchangeMatcherReactiveAuthorizationManager(
List<PayloadExchangeMatcherEntry<ReactiveAuthorizationManager<PayloadExchangeAuthorizationContext>>> mappings) {
Assert.notEmpty(mappings, "mappings cannot be null");
this.mappings = mappings;
}
@@ -49,14 +52,10 @@ public class PayloadExchangeMatcherReactiveAuthorizationManager implements React
public Mono<AuthorizationDecision> check(Mono<Authentication> authentication, PayloadExchange exchange) {
return Flux.fromIterable(this.mappings)
.concatMap(mapping -> mapping.getMatcher().matches(exchange)
.filter(PayloadExchangeMatcher.MatchResult::isMatch)
.map(r -> r.getVariables())
.flatMap(variables -> mapping.getEntry()
.check(authentication, new PayloadExchangeAuthorizationContext(exchange, variables))
)
)
.next()
.switchIfEmpty(Mono.fromCallable(() -> new AuthorizationDecision(false)));
.filter(PayloadExchangeMatcher.MatchResult::isMatch).map(r -> r.getVariables())
.flatMap(variables -> mapping.getEntry().check(authentication,
new PayloadExchangeAuthorizationContext(exchange, variables))))
.next().switchIfEmpty(Mono.fromCallable(() -> new AuthorizationDecision(false)));
}
public static PayloadExchangeMatcherReactiveAuthorizationManager.Builder builder() {
@@ -64,6 +63,7 @@ public class PayloadExchangeMatcherReactiveAuthorizationManager implements React
}
public static class Builder {
private final List<PayloadExchangeMatcherEntry<ReactiveAuthorizationManager<PayloadExchangeAuthorizationContext>>> mappings = new ArrayList<>();
private Builder() {
@@ -78,5 +78,7 @@ public class PayloadExchangeMatcherReactiveAuthorizationManager implements React
public PayloadExchangeMatcherReactiveAuthorizationManager build() {
return new PayloadExchangeMatcherReactiveAuthorizationManager(this.mappings);
}
}
}
@@ -26,8 +26,9 @@ import java.util.List;
import java.util.ListIterator;
/**
* A {@link PayloadInterceptorChain} which exposes the Reactor {@link Context} via a member variable.
* This class is not Thread safe, so a new instance must be created for each Thread.
* A {@link PayloadInterceptorChain} which exposes the Reactor {@link Context} via a
* member variable. This class is not Thread safe, so a new instance must be created for
* each Thread.
*
* Internally {@code ContextPayloadInterceptorChain} is used to ensure that the Reactor
* {@code Context} is captured so it can be transferred to subscribers outside of this
@@ -72,13 +73,8 @@ class ContextPayloadInterceptorChain implements PayloadInterceptorChain {
}
public Mono<Void> next(PayloadExchange exchange) {
return Mono.defer(() ->
shouldIntercept() ?
this.currentInterceptor.intercept(exchange, this.next) :
Mono.subscriberContext()
.doOnNext(c -> this.context = c)
.then()
);
return Mono.defer(() -> shouldIntercept() ? this.currentInterceptor.intercept(exchange, this.next)
: Mono.subscriberContext().doOnNext(c -> this.context = c).then());
}
Context getContext() {
@@ -96,4 +92,5 @@ class ContextPayloadInterceptorChain implements PayloadInterceptorChain {
public String toString() {
return getClass().getSimpleName() + "[currentInterceptor=" + this.currentInterceptor + "]";
}
}
@@ -69,4 +69,5 @@ public class DefaultPayloadExchange implements PayloadExchange {
public MimeType getDataMimeType() {
return this.dataMimeType;
}
}
@@ -31,10 +31,12 @@ import java.util.List;
/**
* Combines the {@link PayloadInterceptor} with an {@link RSocketProxy}
*
* @author Rob Winch
* @since 5.2
*/
class PayloadInterceptorRSocket extends RSocketProxy {
private final List<PayloadInterceptor> interceptors;
private final MimeType metadataMimeType;
@@ -43,14 +45,12 @@ class PayloadInterceptorRSocket extends RSocketProxy {
private final Context context;
PayloadInterceptorRSocket(RSocket delegate,
List<PayloadInterceptor> interceptors, MimeType metadataMimeType,
PayloadInterceptorRSocket(RSocket delegate, List<PayloadInterceptor> interceptors, MimeType metadataMimeType,
MimeType dataMimeType) {
this(delegate, interceptors, metadataMimeType, dataMimeType, Context.empty());
}
PayloadInterceptorRSocket(RSocket delegate,
List<PayloadInterceptor> interceptors, MimeType metadataMimeType,
PayloadInterceptorRSocket(RSocket delegate, List<PayloadInterceptor> interceptors, MimeType metadataMimeType,
MimeType dataMimeType, Context context) {
super(delegate);
this.metadataMimeType = metadataMimeType;
@@ -71,71 +71,52 @@ class PayloadInterceptorRSocket extends RSocketProxy {
@Override
public Mono<Void> fireAndForget(Payload payload) {
return intercept(PayloadExchangeType.FIRE_AND_FORGET, payload)
.flatMap(context ->
this.source.fireAndForget(payload)
.subscriberContext(context)
);
.flatMap(context -> this.source.fireAndForget(payload).subscriberContext(context));
}
@Override
public Mono<Payload> requestResponse(Payload payload) {
return intercept(PayloadExchangeType.REQUEST_RESPONSE, payload)
.flatMap(context ->
this.source.requestResponse(payload)
.subscriberContext(context)
);
.flatMap(context -> this.source.requestResponse(payload).subscriberContext(context));
}
@Override
public Flux<Payload> requestStream(Payload payload) {
return intercept(PayloadExchangeType.REQUEST_STREAM, payload)
.flatMapMany(context ->
this.source.requestStream(payload)
.subscriberContext(context)
);
.flatMapMany(context -> this.source.requestStream(payload).subscriberContext(context));
}
@Override
public Flux<Payload> requestChannel(Publisher<Payload> payloads) {
return Flux.from(payloads)
.switchOnFirst((signal, innerFlux) -> {
Payload firstPayload = signal.get();
return intercept(PayloadExchangeType.REQUEST_CHANNEL, firstPayload)
.flatMapMany(context ->
innerFlux
.skip(1)
.flatMap(p -> intercept(PayloadExchangeType.PAYLOAD, p).thenReturn(p))
return Flux.from(payloads).switchOnFirst((signal, innerFlux) -> {
Payload firstPayload = signal.get();
return intercept(PayloadExchangeType.REQUEST_CHANNEL, firstPayload).flatMapMany(
context -> innerFlux.skip(1).flatMap(p -> intercept(PayloadExchangeType.PAYLOAD, p).thenReturn(p))
.transform(securedPayloads -> Flux.concat(Flux.just(firstPayload), securedPayloads))
.transform(securedPayloads -> this.source.requestChannel(securedPayloads))
.subscriberContext(context)
);
});
.subscriberContext(context));
});
}
@Override
public Mono<Void> metadataPush(Payload payload) {
return intercept(PayloadExchangeType.METADATA_PUSH, payload)
.flatMap(c -> this.source
.metadataPush(payload)
.subscriberContext(c)
);
.flatMap(c -> this.source.metadataPush(payload).subscriberContext(c));
}
private Mono<Context> intercept(PayloadExchangeType type, Payload payload) {
return Mono.defer(() -> {
ContextPayloadInterceptorChain chain = new ContextPayloadInterceptorChain(this.interceptors);
DefaultPayloadExchange exchange = new DefaultPayloadExchange(type, payload,
this.metadataMimeType, this.dataMimeType);
return chain.next(exchange)
.then(Mono.fromCallable(() -> chain.getContext()))
.defaultIfEmpty(Context.empty())
.subscriberContext(this.context);
DefaultPayloadExchange exchange = new DefaultPayloadExchange(type, payload, this.metadataMimeType,
this.dataMimeType);
return chain.next(exchange).then(Mono.fromCallable(() -> chain.getContext()))
.defaultIfEmpty(Context.empty()).subscriberContext(this.context);
});
}
@Override
public String toString() {
return getClass().getSimpleName() + "[source=" + this.source + ",interceptors="
+ this.interceptors + "]";
return getClass().getSimpleName() + "[source=" + this.source + ",interceptors=" + this.interceptors + "]";
}
}
@@ -38,6 +38,7 @@ import java.util.List;
* @since 5.2
*/
class PayloadSocketAcceptor implements SocketAcceptor {
private final SocketAcceptor delegate;
private final List<PayloadInterceptor> interceptors;
@@ -45,8 +46,8 @@ class PayloadSocketAcceptor implements SocketAcceptor {
@Nullable
private MimeType defaultDataMimeType;
private MimeType defaultMetadataMimeType =
MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
private MimeType defaultMetadataMimeType = MimeTypeUtils
.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
PayloadSocketAcceptor(SocketAcceptor delegate, List<PayloadInterceptor> interceptors) {
Assert.notNull(delegate, "delegate cannot be null");
@@ -70,10 +71,11 @@ class PayloadSocketAcceptor implements SocketAcceptor {
// FIXME do we want to make the sendingSocket available in the PayloadExchange
return intercept(setup, dataMimeType, metadataMimeType)
.flatMap(ctx -> this.delegate.accept(setup, sendingSocket)
.map(acceptingSocket -> new PayloadInterceptorRSocket(acceptingSocket, this.interceptors, metadataMimeType, dataMimeType, ctx))
.subscriberContext(ctx)
);
.flatMap(
ctx -> this.delegate.accept(setup, sendingSocket)
.map(acceptingSocket -> new PayloadInterceptorRSocket(acceptingSocket,
this.interceptors, metadataMimeType, dataMimeType, ctx))
.subscriberContext(ctx));
}
private Mono<Context> intercept(Payload payload, MimeType dataMimeType, MimeType metadataMimeType) {
@@ -81,8 +83,7 @@ class PayloadSocketAcceptor implements SocketAcceptor {
ContextPayloadInterceptorChain chain = new ContextPayloadInterceptorChain(this.interceptors);
DefaultPayloadExchange exchange = new DefaultPayloadExchange(PayloadExchangeType.SETUP, payload,
metadataMimeType, dataMimeType);
return chain.next(exchange)
.then(Mono.fromCallable(() -> chain.getContext()))
return chain.next(exchange).then(Mono.fromCallable(() -> chain.getContext()))
.defaultIfEmpty(Context.empty());
});
}
@@ -99,4 +100,5 @@ class PayloadSocketAcceptor implements SocketAcceptor {
Assert.notNull(defaultMetadataMimeType, "defaultMetadataMimeType cannot be null");
this.defaultMetadataMimeType = defaultMetadataMimeType;
}
}
@@ -40,8 +40,8 @@ public class PayloadSocketAcceptorInterceptor implements SocketAcceptorIntercept
@Nullable
private MimeType defaultDataMimeType;
private MimeType defaultMetadataMimeType =
MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
private MimeType defaultMetadataMimeType = MimeTypeUtils
.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
public PayloadSocketAcceptorInterceptor(List<PayloadInterceptor> interceptors) {
this.interceptors = interceptors;
@@ -49,8 +49,7 @@ public class PayloadSocketAcceptorInterceptor implements SocketAcceptorIntercept
@Override
public SocketAcceptor apply(SocketAcceptor socketAcceptor) {
PayloadSocketAcceptor acceptor = new PayloadSocketAcceptor(
socketAcceptor, this.interceptors);
PayloadSocketAcceptor acceptor = new PayloadSocketAcceptor(socketAcceptor, this.interceptors);
acceptor.setDefaultDataMimeType(this.defaultDataMimeType);
acceptor.setDefaultMetadataMimeType(this.defaultMetadataMimeType);
return acceptor;
@@ -64,4 +63,5 @@ public class PayloadSocketAcceptorInterceptor implements SocketAcceptorIntercept
Assert.notNull(defaultMetadataMimeType, "defaultMetadataMimeType cannot be null");
this.defaultMetadataMimeType = defaultMetadataMimeType;
}
}
@@ -21,13 +21,15 @@ import io.rsocket.plugins.SocketAcceptorInterceptor;
import org.springframework.util.Assert;
/**
* A SocketAcceptorInterceptor that applies Security through a delegate {@link SocketAcceptorInterceptor}. This allows
* security to be applied lazily to an application.
* A SocketAcceptorInterceptor that applies Security through a delegate
* {@link SocketAcceptorInterceptor}. This allows security to be applied lazily to an
* application.
*
* @author Rob Winch
* @since 5.2
*/
public class SecuritySocketAcceptorInterceptor implements SocketAcceptorInterceptor {
private final SocketAcceptorInterceptor acceptorInterceptor;
public SecuritySocketAcceptorInterceptor(SocketAcceptorInterceptor acceptorInterceptor) {
@@ -39,4 +41,5 @@ public class SecuritySocketAcceptorInterceptor implements SocketAcceptorIntercep
public SocketAcceptor apply(SocketAcceptor socketAcceptor) {
return this.acceptorInterceptor.apply(socketAcceptor);
}
}
@@ -31,48 +31,47 @@ import java.util.Map;
*
* @author Rob Winch
* @since 5.2
* @deprecated Basic Authentication did not evolve into a standard. Use Simple Authentication instead.
* @deprecated Basic Authentication did not evolve into a standard. Use Simple
* Authentication instead.
*/
@Deprecated
public class BasicAuthenticationDecoder extends AbstractDecoder<UsernamePasswordMetadata> {
public BasicAuthenticationDecoder() {
super(UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE);
}
@Override
public Flux<UsernamePasswordMetadata> decode(Publisher<DataBuffer> input,
ResolvableType elementType, MimeType mimeType, Map<String, Object> hints) {
return Flux.from(input)
.map(DataBuffer::asByteBuffer)
.map(byteBuffer -> {
byte[] sizeBytes = new byte[4];
byteBuffer.get(sizeBytes);
public Flux<UsernamePasswordMetadata> decode(Publisher<DataBuffer> input, ResolvableType elementType,
MimeType mimeType, Map<String, Object> hints) {
return Flux.from(input).map(DataBuffer::asByteBuffer).map(byteBuffer -> {
byte[] sizeBytes = new byte[4];
byteBuffer.get(sizeBytes);
int usernameSize = 4;
byte[] usernameBytes = new byte[usernameSize];
byteBuffer.get(usernameBytes);
byte[] passwordBytes = new byte[byteBuffer.remaining()];
byteBuffer.get(passwordBytes);
String username = new String(usernameBytes);
String password = new String(passwordBytes);
return new UsernamePasswordMetadata(username, password);
});
int usernameSize = 4;
byte[] usernameBytes = new byte[usernameSize];
byteBuffer.get(usernameBytes);
byte[] passwordBytes = new byte[byteBuffer.remaining()];
byteBuffer.get(passwordBytes);
String username = new String(usernameBytes);
String password = new String(passwordBytes);
return new UsernamePasswordMetadata(username, password);
});
}
@Override
public Mono<UsernamePasswordMetadata> decodeToMono(Publisher<DataBuffer> input,
ResolvableType elementType, MimeType mimeType, Map<String, Object> hints) {
return Mono.from(input)
.map(DataBuffer::asByteBuffer)
.map(byteBuffer -> {
int usernameSize = byteBuffer.getInt();
byte[] usernameBytes = new byte[usernameSize];
byteBuffer.get(usernameBytes);
byte[] passwordBytes = new byte[byteBuffer.remaining()];
byteBuffer.get(passwordBytes);
String username = new String(usernameBytes);
String password = new String(passwordBytes);
return new UsernamePasswordMetadata(username, password);
});
public Mono<UsernamePasswordMetadata> decodeToMono(Publisher<DataBuffer> input, ResolvableType elementType,
MimeType mimeType, Map<String, Object> hints) {
return Mono.from(input).map(DataBuffer::asByteBuffer).map(byteBuffer -> {
int usernameSize = byteBuffer.getInt();
byte[] usernameBytes = new byte[usernameSize];
byteBuffer.get(usernameBytes);
byte[] passwordBytes = new byte[byteBuffer.remaining()];
byteBuffer.get(passwordBytes);
String username = new String(usernameBytes);
String password = new String(passwordBytes);
return new UsernamePasswordMetadata(username, password);
});
}
}
@@ -34,29 +34,26 @@ import java.util.Map;
*
* @author Rob Winch
* @since 5.2
* @deprecated Basic Authentication did not evolve into a standard. use {@link SimpleAuthenticationEncoder}
* @deprecated Basic Authentication did not evolve into a standard. use
* {@link SimpleAuthenticationEncoder}
*/
@Deprecated
public class BasicAuthenticationEncoder extends
AbstractEncoder<UsernamePasswordMetadata> {
public class BasicAuthenticationEncoder extends AbstractEncoder<UsernamePasswordMetadata> {
public BasicAuthenticationEncoder() {
super(UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE);
}
@Override
public Flux<DataBuffer> encode(
Publisher<? extends UsernamePasswordMetadata> inputStream,
DataBufferFactory bufferFactory, ResolvableType elementType,
MimeType mimeType, Map<String, Object> hints) {
return Flux.from(inputStream).map(credentials ->
encodeValue(credentials, bufferFactory, elementType, mimeType, hints));
public Flux<DataBuffer> encode(Publisher<? extends UsernamePasswordMetadata> inputStream,
DataBufferFactory bufferFactory, ResolvableType elementType, MimeType mimeType, Map<String, Object> hints) {
return Flux.from(inputStream)
.map(credentials -> encodeValue(credentials, bufferFactory, elementType, mimeType, hints));
}
@Override
public DataBuffer encodeValue(UsernamePasswordMetadata credentials,
DataBufferFactory bufferFactory, ResolvableType valueType, MimeType mimeType,
Map<String, Object> hints) {
public DataBuffer encodeValue(UsernamePasswordMetadata credentials, DataBufferFactory bufferFactory,
ResolvableType valueType, MimeType mimeType, Map<String, Object> hints) {
String username = credentials.getUsername();
String password = credentials.getPassword();
byte[] usernameBytes = username.getBytes(StandardCharsets.UTF_8);
@@ -69,10 +66,12 @@ public class BasicAuthenticationEncoder extends
metadata.write(password.getBytes(StandardCharsets.UTF_8));
release = false;
return metadata;
} finally {
}
finally {
if (release) {
DataBufferUtils.release(metadata);
}
}
}
}
@@ -32,15 +32,17 @@ import reactor.core.publisher.Flux;
import java.util.Map;
/**
* Encodes <a href="https://github.com/rsocket/rsocket/blob/5920ed374d008abb712cb1fd7c9d91778b2f4a68/Extensions/Security/Bearer.md">Bearer Authentication</a>.
* Encodes <a href=
* "https://github.com/rsocket/rsocket/blob/5920ed374d008abb712cb1fd7c9d91778b2f4a68/Extensions/Security/Bearer.md">Bearer
* Authentication</a>.
*
* @author Rob Winch
* @since 5.3
*/
public class BearerTokenAuthenticationEncoder extends
AbstractEncoder<BearerTokenMetadata> {
public class BearerTokenAuthenticationEncoder extends AbstractEncoder<BearerTokenMetadata> {
private static final MimeType AUTHENTICATION_MIME_TYPE = MimeTypeUtils.parseMimeType("message/x.rsocket.authentication.v0");
private static final MimeType AUTHENTICATION_MIME_TYPE = MimeTypeUtils
.parseMimeType("message/x.rsocket.authentication.v0");
private NettyDataBufferFactory defaultBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
@@ -49,23 +51,19 @@ public class BearerTokenAuthenticationEncoder extends
}
@Override
public Flux<DataBuffer> encode(
Publisher<? extends BearerTokenMetadata> inputStream,
DataBufferFactory bufferFactory, ResolvableType elementType,
MimeType mimeType, Map<String, Object> hints) {
return Flux.from(inputStream).map(credentials ->
encodeValue(credentials, bufferFactory, elementType, mimeType, hints));
public Flux<DataBuffer> encode(Publisher<? extends BearerTokenMetadata> inputStream,
DataBufferFactory bufferFactory, ResolvableType elementType, MimeType mimeType, Map<String, Object> hints) {
return Flux.from(inputStream)
.map(credentials -> encodeValue(credentials, bufferFactory, elementType, mimeType, hints));
}
@Override
public DataBuffer encodeValue(BearerTokenMetadata credentials,
DataBufferFactory bufferFactory, ResolvableType valueType, MimeType mimeType,
Map<String, Object> hints) {
public DataBuffer encodeValue(BearerTokenMetadata credentials, DataBufferFactory bufferFactory,
ResolvableType valueType, MimeType mimeType, Map<String, Object> hints) {
String token = credentials.getToken();
NettyDataBufferFactory factory = nettyFactory(bufferFactory);
ByteBufAllocator allocator = factory.getByteBufAllocator();
ByteBuf simpleAuthentication = AuthMetadataCodec
.encodeBearerMetadata(allocator, token.toCharArray());
ByteBuf simpleAuthentication = AuthMetadataCodec.encodeBearerMetadata(allocator, token.toCharArray());
return factory.wrap(simpleAuthentication);
}
@@ -75,4 +73,5 @@ public class BearerTokenAuthenticationEncoder extends
}
return this.defaultBufferFactory;
}
}
@@ -14,28 +14,30 @@
* limitations under the License.
*/
package org.springframework.security.rsocket.metadata;
import org.springframework.http.MediaType;
import org.springframework.util.MimeType;
/**
* Represents a bearer token that has been encoded into a
* {@link Payload#metadata()}.
* Represents a bearer token that has been encoded into a {@link Payload#metadata()}.
*
* @author Rob Winch
* @since 5.2
*/
public class BearerTokenMetadata {
/**
* Represents a bearer token which is encoded as a String.
*
* See <a href="https://github.com/rsocket/rsocket/issues/272">rsocket/rsocket#272</a>
* @deprecated Basic did not evolve into the standard. Instead use Simple Authentication MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_AUTHENTICATION.getString())
* @deprecated Basic did not evolve into the standard. Instead use Simple
* Authentication
* MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_AUTHENTICATION.getString())
*/
@Deprecated
public static final MimeType BEARER_AUTHENTICATION_MIME_TYPE = new MediaType("message", "x.rsocket.authentication.bearer.v0");
public static final MimeType BEARER_AUTHENTICATION_MIME_TYPE = new MediaType("message",
"x.rsocket.authentication.bearer.v0");
private final String token;
@@ -46,4 +48,5 @@ public class BearerTokenMetadata {
public String getToken() {
return this.token;
}
}
@@ -32,17 +32,17 @@ import reactor.core.publisher.Flux;
import java.util.Map;
/**
* Encodes
* <a href="https://github.com/rsocket/rsocket/blob/5920ed374d008abb712cb1fd7c9d91778b2f4a68/Extensions/Security/Simple.md">Simple</a>
* Encodes <a href=
* "https://github.com/rsocket/rsocket/blob/5920ed374d008abb712cb1fd7c9d91778b2f4a68/Extensions/Security/Simple.md">Simple</a>
* Authentication.
*
* @author Rob Winch
* @since 5.3
*/
public class SimpleAuthenticationEncoder extends
AbstractEncoder<UsernamePasswordMetadata> {
public class SimpleAuthenticationEncoder extends AbstractEncoder<UsernamePasswordMetadata> {
private static final MimeType AUTHENTICATION_MIME_TYPE = MimeTypeUtils.parseMimeType("message/x.rsocket.authentication.v0");
private static final MimeType AUTHENTICATION_MIME_TYPE = MimeTypeUtils
.parseMimeType("message/x.rsocket.authentication.v0");
private NettyDataBufferFactory defaultBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
@@ -51,24 +51,21 @@ public class SimpleAuthenticationEncoder extends
}
@Override
public Flux<DataBuffer> encode(
Publisher<? extends UsernamePasswordMetadata> inputStream,
DataBufferFactory bufferFactory, ResolvableType elementType,
MimeType mimeType, Map<String, Object> hints) {
return Flux.from(inputStream).map(credentials ->
encodeValue(credentials, bufferFactory, elementType, mimeType, hints));
public Flux<DataBuffer> encode(Publisher<? extends UsernamePasswordMetadata> inputStream,
DataBufferFactory bufferFactory, ResolvableType elementType, MimeType mimeType, Map<String, Object> hints) {
return Flux.from(inputStream)
.map(credentials -> encodeValue(credentials, bufferFactory, elementType, mimeType, hints));
}
@Override
public DataBuffer encodeValue(UsernamePasswordMetadata credentials,
DataBufferFactory bufferFactory, ResolvableType valueType, MimeType mimeType,
Map<String, Object> hints) {
public DataBuffer encodeValue(UsernamePasswordMetadata credentials, DataBufferFactory bufferFactory,
ResolvableType valueType, MimeType mimeType, Map<String, Object> hints) {
String username = credentials.getUsername();
String password = credentials.getPassword();
NettyDataBufferFactory factory = nettyFactory(bufferFactory);
ByteBufAllocator allocator = factory.getByteBufAllocator();
ByteBuf simpleAuthentication = AuthMetadataCodec
.encodeSimpleMetadata(allocator, username.toCharArray(), password.toCharArray());
ByteBuf simpleAuthentication = AuthMetadataCodec.encodeSimpleMetadata(allocator, username.toCharArray(),
password.toCharArray());
return factory.wrap(simpleAuthentication);
}
@@ -78,4 +75,5 @@ public class SimpleAuthenticationEncoder extends
}
return this.defaultBufferFactory;
}
}
@@ -28,15 +28,19 @@ import org.springframework.util.MimeType;
* @since 5.2
*/
public final class UsernamePasswordMetadata {
/**
* Represents a username password which is encoded as
* {@code ${username-bytes-length}${username-bytes}${password-bytes}}.
*
* See <a href="https://github.com/rsocket/rsocket/issues/272">rsocket/rsocket#272</a>
* @deprecated Basic did not evolve into the standard. Instead use Simple Authentication MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_AUTHENTICATION.getString())
* @deprecated Basic did not evolve into the standard. Instead use Simple
* Authentication
* MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_AUTHENTICATION.getString())
*/
@Deprecated
public static final MimeType BASIC_AUTHENTICATION_MIME_TYPE = new MediaType("message", "x.rsocket.authentication.basic.v0");
public static final MimeType BASIC_AUTHENTICATION_MIME_TYPE = new MediaType("message",
"x.rsocket.authentication.basic.v0");
private final String username;
@@ -54,4 +58,5 @@ public final class UsernamePasswordMetadata {
public String getPassword() {
return this.password;
}
}
@@ -26,7 +26,9 @@ import java.util.Map;
* @since 5.2
*/
public class PayloadExchangeAuthorizationContext {
private final PayloadExchange exchange;
private final Map<String, Object> variables;
public PayloadExchangeAuthorizationContext(PayloadExchange exchange) {
@@ -45,4 +47,5 @@ public class PayloadExchangeAuthorizationContext {
public Map<String, Object> getVariables() {
return Collections.unmodifiableMap(this.variables);
}
}
@@ -24,6 +24,7 @@ import java.util.Map;
/**
* An interface for determining if a {@link PayloadExchangeMatcher} matches.
*
* @author Rob Winch
* @since 5.2
*/
@@ -40,7 +41,9 @@ public interface PayloadExchangeMatcher {
* The result of matching
*/
class MatchResult {
private final boolean match;
private final Map<String, Object> variables;
private MatchResult(boolean match, Map<String, Object> variables) {
@@ -70,7 +73,8 @@ public interface PayloadExchangeMatcher {
/**
*
* Creates an instance of {@link MatchResult} that is a match with the specified variables
* Creates an instance of {@link MatchResult} that is a match with the specified
* variables
* @param variables
* @return
*/
@@ -85,5 +89,7 @@ public interface PayloadExchangeMatcher {
public static Mono<MatchResult> notMatch() {
return Mono.just(new MatchResult(false, Collections.emptyMap()));
}
}
}
@@ -20,7 +20,9 @@ package org.springframework.security.rsocket.util.matcher;
* @author Rob Winch
*/
public class PayloadExchangeMatcherEntry<T> {
private final PayloadExchangeMatcher matcher;
private final T entry;
public PayloadExchangeMatcherEntry(PayloadExchangeMatcher matcher, T entry) {
@@ -35,4 +37,5 @@ public class PayloadExchangeMatcherEntry<T> {
public T getEntry() {
return this.entry;
}
}
@@ -28,9 +28,8 @@ public abstract class PayloadExchangeMatchers {
public static PayloadExchangeMatcher setup() {
return new PayloadExchangeMatcher() {
public Mono<MatchResult> matches(PayloadExchange exchange) {
return PayloadExchangeType.SETUP.equals(exchange.getType()) ?
MatchResult.match() :
MatchResult.notMatch();
return PayloadExchangeType.SETUP.equals(exchange.getType()) ? MatchResult.match()
: MatchResult.notMatch();
}
};
}
@@ -38,9 +37,7 @@ public abstract class PayloadExchangeMatchers {
public static PayloadExchangeMatcher anyRequest() {
return new PayloadExchangeMatcher() {
public Mono<MatchResult> matches(PayloadExchange exchange) {
return exchange.getType().isRequest() ?
MatchResult.match() :
MatchResult.notMatch();
return exchange.getType().isRequest() ? MatchResult.match() : MatchResult.notMatch();
}
};
}
@@ -53,5 +50,7 @@ public abstract class PayloadExchangeMatchers {
};
}
private PayloadExchangeMatchers() {}
private PayloadExchangeMatchers() {
}
}
@@ -27,7 +27,7 @@ import java.util.Optional;
/**
* FIXME: Pay attention to the package this goes into. It requires spring-messaging for
* the MetadataExtractor.
* the MetadataExtractor.
*
* @author Rob Winch
* @since 5.2
@@ -40,8 +40,7 @@ public class RoutePayloadExchangeMatcher implements PayloadExchangeMatcher {
private final RouteMatcher routeMatcher;
public RoutePayloadExchangeMatcher(MetadataExtractor metadataExtractor,
RouteMatcher routeMatcher, String pattern) {
public RoutePayloadExchangeMatcher(MetadataExtractor metadataExtractor, RouteMatcher routeMatcher, String pattern) {
Assert.notNull(pattern, "pattern cannot be null");
this.metadataExtractor = metadataExtractor;
this.routeMatcher = routeMatcher;
@@ -50,12 +49,12 @@ public class RoutePayloadExchangeMatcher implements PayloadExchangeMatcher {
@Override
public Mono<MatchResult> matches(PayloadExchange exchange) {
Map<String, Object> metadata = this.metadataExtractor
.extract(exchange.getPayload(), exchange.getMetadataMimeType());
Map<String, Object> metadata = this.metadataExtractor.extract(exchange.getPayload(),
exchange.getMetadataMimeType());
return Optional.ofNullable((String) metadata.get(MetadataExtractor.ROUTE_KEY))
.map(routeValue -> this.routeMatcher.parseRoute(routeValue))
.map(route -> this.routeMatcher.matchAndExtract(this.pattern, route))
.map(v -> MatchResult.match(v))
.orElse(MatchResult.notMatch());
.map(routeValue -> this.routeMatcher.parseRoute(routeValue))
.map(route -> this.routeMatcher.matchAndExtract(this.pattern, route)).map(v -> MatchResult.match(v))
.orElse(MatchResult.notMatch());
}
}
@@ -38,6 +38,7 @@ import static org.assertj.core.api.Assertions.*;
*/
@RunWith(MockitoJUnitRunner.class)
public class AnonymousPayloadInterceptorTests {
@Mock
private PayloadExchange exchange;
@@ -51,31 +52,27 @@ public class AnonymousPayloadInterceptorTests {
@Test
public void constructorKeyWhenKeyNullThenException() {
String key = null;
assertThatCode(() -> new AnonymousPayloadInterceptor(key))
.isInstanceOf(IllegalArgumentException.class);
assertThatCode(() -> new AnonymousPayloadInterceptor(key)).isInstanceOf(IllegalArgumentException.class);
}
@Test
public void constructorKeyPrincipalAuthoritiesWhenKeyNullThenException() {
String key = null;
assertThatCode(() -> new AnonymousPayloadInterceptor(key, "principal",
AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")))
.isInstanceOf(IllegalArgumentException.class);
AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"))).isInstanceOf(IllegalArgumentException.class);
}
@Test
public void constructorKeyPrincipalAuthoritiesWhenPrincipalNullThenException() {
Object principal = null;
assertThatCode(() -> new AnonymousPayloadInterceptor("key", principal,
AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")))
.isInstanceOf(IllegalArgumentException.class);
AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"))).isInstanceOf(IllegalArgumentException.class);
}
@Test
public void constructorKeyPrincipalAuthoritiesWhenAuthoritiesNullThenException() {
List<GrantedAuthority> authorities = null;
assertThatCode(() -> new AnonymousPayloadInterceptor("key", "principal",
authorities))
assertThatCode(() -> new AnonymousPayloadInterceptor("key", "principal", authorities))
.isInstanceOf(IllegalArgumentException.class);
}
@@ -93,15 +90,14 @@ public class AnonymousPayloadInterceptorTests {
@Test
public void interceptWhenAuthenticationThenOriginalAuthentication() {
AuthenticationPayloadInterceptorChain chain = new AuthenticationPayloadInterceptorChain();
TestingAuthenticationToken expected =
new TestingAuthenticationToken("test", "password");
TestingAuthenticationToken expected = new TestingAuthenticationToken("test", "password");
this.interceptor.intercept(this.exchange, chain)
.subscriberContext(ReactiveSecurityContextHolder.withAuthentication(expected))
.block();
.subscriberContext(ReactiveSecurityContextHolder.withAuthentication(expected)).block();
Authentication authentication = chain.getAuthentication();
assertThat(authentication).isEqualTo(expected);
}
}
@@ -27,6 +27,7 @@ import org.springframework.security.rsocket.api.PayloadExchange;
* @author Rob Winch
*/
class AuthenticationPayloadInterceptorChain implements PayloadInterceptorChain {
private Authentication authentication;
@Override
@@ -42,4 +43,5 @@ class AuthenticationPayloadInterceptorChain implements PayloadInterceptorChain {
public void setAuthentication(Authentication authentication) {
this.authentication = authentication;
}
}
@@ -62,8 +62,10 @@ import static org.mockito.Mockito.when;
*/
@RunWith(MockitoJUnitRunner.class)
public class AuthenticationPayloadInterceptorTests {
static final MimeType COMPOSITE_METADATA = MimeTypeUtils.parseMimeType(
WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
static final MimeType COMPOSITE_METADATA = MimeTypeUtils
.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
@Mock
ReactiveAuthenticationManager authenticationManager;
@@ -72,50 +74,41 @@ public class AuthenticationPayloadInterceptorTests {
@Test
public void constructorWhenAuthenticationManagerNullThenException() {
assertThatCode(() -> new AuthenticationPayloadInterceptor(null))
.isInstanceOf(IllegalArgumentException.class);
assertThatCode(() -> new AuthenticationPayloadInterceptor(null)).isInstanceOf(IllegalArgumentException.class);
}
@Test
public void interceptWhenBasicCredentialsThenAuthenticates() {
AuthenticationPayloadInterceptor interceptor = new AuthenticationPayloadInterceptor(
this.authenticationManager);
AuthenticationPayloadInterceptor interceptor = new AuthenticationPayloadInterceptor(this.authenticationManager);
PayloadExchange exchange = createExchange();
TestingAuthenticationToken expectedAuthentication =
new TestingAuthenticationToken("user", "password");
when(this.authenticationManager.authenticate(any())).thenReturn(Mono.just(
expectedAuthentication));
TestingAuthenticationToken expectedAuthentication = new TestingAuthenticationToken("user", "password");
when(this.authenticationManager.authenticate(any())).thenReturn(Mono.just(expectedAuthentication));
AuthenticationPayloadInterceptorChain authenticationPayloadChain = new AuthenticationPayloadInterceptorChain();
interceptor.intercept(exchange, authenticationPayloadChain)
.block();
interceptor.intercept(exchange, authenticationPayloadChain).block();
Authentication authentication = authenticationPayloadChain.getAuthentication();
verify(this.authenticationManager).authenticate(this.authenticationArg.capture());
assertThat(this.authenticationArg.getValue()).isEqualToComparingFieldByField(new UsernamePasswordAuthenticationToken("user", "password"));
assertThat(this.authenticationArg.getValue())
.isEqualToComparingFieldByField(new UsernamePasswordAuthenticationToken("user", "password"));
assertThat(authentication).isEqualTo(expectedAuthentication);
}
@Test
public void interceptWhenAuthenticationSuccessThenChainSubscribedOnce() {
AuthenticationPayloadInterceptor interceptor = new AuthenticationPayloadInterceptor(
this.authenticationManager);
AuthenticationPayloadInterceptor interceptor = new AuthenticationPayloadInterceptor(this.authenticationManager);
PayloadExchange exchange = createExchange();
TestingAuthenticationToken expectedAuthentication =
new TestingAuthenticationToken("user", "password");
when(this.authenticationManager.authenticate(any())).thenReturn(Mono.just(
expectedAuthentication));
TestingAuthenticationToken expectedAuthentication = new TestingAuthenticationToken("user", "password");
when(this.authenticationManager.authenticate(any())).thenReturn(Mono.just(expectedAuthentication));
PublisherProbe<Void> voidResult = PublisherProbe.empty();
PayloadInterceptorChain chain = mock(PayloadInterceptorChain.class);
when(chain.next(any())).thenReturn(voidResult.mono());
StepVerifier.create(interceptor.intercept(exchange, chain))
.then(() -> assertThat(voidResult.subscribeCount()).isEqualTo(1))
.verifyComplete();
.then(() -> assertThat(voidResult.subscribeCount()).isEqualTo(1)).verifyComplete();
}
private Payload createRequestPayload() {
@@ -123,25 +116,22 @@ public class AuthenticationPayloadInterceptorTests {
UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("user", "password");
BasicAuthenticationEncoder encoder = new BasicAuthenticationEncoder();
DefaultDataBufferFactory factory = new DefaultDataBufferFactory();
ResolvableType elementType = ResolvableType
.forClass(UsernamePasswordMetadata.class);
ResolvableType elementType = ResolvableType.forClass(UsernamePasswordMetadata.class);
MimeType mimeType = UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE;
Map<String, Object> hints = null;
DataBuffer dataBuffer = encoder.encodeValue(credentials, factory,
elementType, mimeType, hints);
DataBuffer dataBuffer = encoder.encodeValue(credentials, factory, elementType, mimeType, hints);
ByteBufAllocator allocator = ByteBufAllocator.DEFAULT;
CompositeByteBuf metadata = allocator.compositeBuffer();
CompositeMetadataCodec.encodeAndAddMetadata(
metadata, allocator, mimeType.toString(), NettyDataBufferFactory.toByteBuf(dataBuffer));
CompositeMetadataCodec.encodeAndAddMetadata(metadata, allocator, mimeType.toString(),
NettyDataBufferFactory.toByteBuf(dataBuffer));
return DefaultPayload.create(allocator.buffer(),
metadata);
return DefaultPayload.create(allocator.buffer(), metadata);
}
private PayloadExchange createExchange() {
return new DefaultPayloadExchange(PayloadExchangeType.REQUEST_RESPONSE, createRequestPayload(), COMPOSITE_METADATA,
MediaType.APPLICATION_JSON);
return new DefaultPayloadExchange(PayloadExchangeType.REQUEST_RESPONSE, createRequestPayload(),
COMPOSITE_METADATA, MediaType.APPLICATION_JSON);
}
}
@@ -42,6 +42,7 @@ import static org.springframework.security.authorization.AuthorityReactiveAuthor
*/
@RunWith(MockitoJUnitRunner.class)
public class AuthorizationPayloadInterceptorTests {
@Mock
private ReactiveAuthorizationManager<PayloadExchange> authorizationManager;
@@ -59,42 +60,35 @@ public class AuthorizationPayloadInterceptorTests {
public void interceptWhenAuthenticationEmptyAndSubscribedThenException() {
when(this.chain.next(any())).thenReturn(this.chainResult.mono());
AuthorizationPayloadInterceptor interceptor =
new AuthorizationPayloadInterceptor(authenticated());
AuthorizationPayloadInterceptor interceptor = new AuthorizationPayloadInterceptor(authenticated());
StepVerifier.create(interceptor.intercept(this.exchange, this.chain))
.then(() -> this.chainResult.assertWasNotSubscribed())
.verifyError(AuthenticationCredentialsNotFoundException.class);
.then(() -> this.chainResult.assertWasNotSubscribed())
.verifyError(AuthenticationCredentialsNotFoundException.class);
}
@Test
public void interceptWhenAuthenticationNotSubscribedAndEmptyThenCompletes() {
when(this.chain.next(any())).thenReturn(this.chainResult.mono());
when(this.authorizationManager.verify(any(), any()))
.thenReturn(this.managerResult.mono());
when(this.authorizationManager.verify(any(), any())).thenReturn(this.managerResult.mono());
AuthorizationPayloadInterceptor interceptor =
new AuthorizationPayloadInterceptor(this.authorizationManager);
AuthorizationPayloadInterceptor interceptor = new AuthorizationPayloadInterceptor(this.authorizationManager);
StepVerifier.create(interceptor.intercept(this.exchange, this.chain))
.then(() -> this.chainResult.assertWasSubscribed())
.verifyComplete();
.then(() -> this.chainResult.assertWasSubscribed()).verifyComplete();
}
@Test
public void interceptWhenNotAuthorizedThenException() {
when(this.chain.next(any())).thenReturn(this.chainResult.mono());
AuthorizationPayloadInterceptor interceptor =
new AuthorizationPayloadInterceptor(hasRole("USER"));
AuthorizationPayloadInterceptor interceptor = new AuthorizationPayloadInterceptor(hasRole("USER"));
Context userContext = ReactiveSecurityContextHolder
.withAuthentication(new TestingAuthenticationToken("user", "password"));
Mono<Void> intercept = interceptor.intercept(this.exchange, this.chain)
.subscriberContext(userContext);
Mono<Void> intercept = interceptor.intercept(this.exchange, this.chain).subscriberContext(userContext);
StepVerifier.create(intercept)
.then(() -> this.chainResult.assertWasNotSubscribed())
StepVerifier.create(intercept).then(() -> this.chainResult.assertWasNotSubscribed())
.verifyError(AccessDeniedException.class);
}
@@ -102,16 +96,13 @@ public class AuthorizationPayloadInterceptorTests {
public void interceptWhenAuthorizedThenContinues() {
when(this.chain.next(any())).thenReturn(this.chainResult.mono());
AuthorizationPayloadInterceptor interceptor =
new AuthorizationPayloadInterceptor(authenticated());
AuthorizationPayloadInterceptor interceptor = new AuthorizationPayloadInterceptor(authenticated());
Context userContext = ReactiveSecurityContextHolder
.withAuthentication(new TestingAuthenticationToken("user", "password", "ROLE_USER"));
Mono<Void> intercept = interceptor.intercept(this.exchange, this.chain)
.subscriberContext(userContext);
Mono<Void> intercept = interceptor.intercept(this.exchange, this.chain).subscriberContext(userContext);
StepVerifier.create(intercept)
.then(() -> this.chainResult.assertWasSubscribed())
.verifyComplete();
StepVerifier.create(intercept).then(() -> this.chainResult.assertWasSubscribed()).verifyComplete();
}
}
@@ -51,58 +51,47 @@ public class PayloadExchangeMatcherReactiveAuthorizationManagerTests {
@Test
public void checkWhenGrantedThenGranted() {
AuthorizationDecision expected = new AuthorizationDecision(true);
when(this.authz.check(any(), any())).thenReturn(Mono.just(
expected));
PayloadExchangeMatcherReactiveAuthorizationManager manager =
PayloadExchangeMatcherReactiveAuthorizationManager.builder()
.add(new PayloadExchangeMatcherEntry<>(PayloadExchangeMatchers.anyExchange(), this.authz))
.build();
when(this.authz.check(any(), any())).thenReturn(Mono.just(expected));
PayloadExchangeMatcherReactiveAuthorizationManager manager = PayloadExchangeMatcherReactiveAuthorizationManager
.builder().add(new PayloadExchangeMatcherEntry<>(PayloadExchangeMatchers.anyExchange(), this.authz))
.build();
assertThat(manager.check(Mono.empty(), this.exchange).block())
.isEqualTo(expected);
assertThat(manager.check(Mono.empty(), this.exchange).block()).isEqualTo(expected);
}
@Test
public void checkWhenDeniedThenDenied() {
AuthorizationDecision expected = new AuthorizationDecision(false);
when(this.authz.check(any(), any())).thenReturn(Mono.just(
expected));
PayloadExchangeMatcherReactiveAuthorizationManager manager =
PayloadExchangeMatcherReactiveAuthorizationManager.builder()
.add(new PayloadExchangeMatcherEntry<>(PayloadExchangeMatchers.anyExchange(), this.authz))
.build();
when(this.authz.check(any(), any())).thenReturn(Mono.just(expected));
PayloadExchangeMatcherReactiveAuthorizationManager manager = PayloadExchangeMatcherReactiveAuthorizationManager
.builder().add(new PayloadExchangeMatcherEntry<>(PayloadExchangeMatchers.anyExchange(), this.authz))
.build();
assertThat(manager.check(Mono.empty(), this.exchange).block())
.isEqualTo(expected);
assertThat(manager.check(Mono.empty(), this.exchange).block()).isEqualTo(expected);
}
@Test
public void checkWhenFirstMatchThenSecondUsed() {
AuthorizationDecision expected = new AuthorizationDecision(true);
when(this.authz.check(any(), any())).thenReturn(Mono.just(
expected));
PayloadExchangeMatcherReactiveAuthorizationManager manager =
PayloadExchangeMatcherReactiveAuthorizationManager.builder()
.add(new PayloadExchangeMatcherEntry<>(PayloadExchangeMatchers.anyExchange(), this.authz))
.add(new PayloadExchangeMatcherEntry<>(e -> PayloadExchangeMatcher.MatchResult.notMatch(), this.authz2))
.build();
when(this.authz.check(any(), any())).thenReturn(Mono.just(expected));
PayloadExchangeMatcherReactiveAuthorizationManager manager = PayloadExchangeMatcherReactiveAuthorizationManager
.builder().add(new PayloadExchangeMatcherEntry<>(PayloadExchangeMatchers.anyExchange(), this.authz))
.add(new PayloadExchangeMatcherEntry<>(e -> PayloadExchangeMatcher.MatchResult.notMatch(), this.authz2))
.build();
assertThat(manager.check(Mono.empty(), this.exchange).block())
.isEqualTo(expected);
assertThat(manager.check(Mono.empty(), this.exchange).block()).isEqualTo(expected);
}
@Test
public void checkWhenSecondMatchThenSecondUsed() {
AuthorizationDecision expected = new AuthorizationDecision(true);
when(this.authz2.check(any(), any())).thenReturn(Mono.just(
expected));
PayloadExchangeMatcherReactiveAuthorizationManager manager =
PayloadExchangeMatcherReactiveAuthorizationManager.builder()
.add(new PayloadExchangeMatcherEntry<>(e -> PayloadExchangeMatcher.MatchResult.notMatch(), this.authz))
.add(new PayloadExchangeMatcherEntry<>(PayloadExchangeMatchers.anyExchange(), this.authz2))
.build();
when(this.authz2.check(any(), any())).thenReturn(Mono.just(expected));
PayloadExchangeMatcherReactiveAuthorizationManager manager = PayloadExchangeMatcherReactiveAuthorizationManager
.builder()
.add(new PayloadExchangeMatcherEntry<>(e -> PayloadExchangeMatcher.MatchResult.notMatch(), this.authz))
.add(new PayloadExchangeMatcherEntry<>(PayloadExchangeMatchers.anyExchange(), this.authz2)).build();
assertThat(manager.check(Mono.empty(), this.exchange).block())
.isEqualTo(expected);
assertThat(manager.check(Mono.empty(), this.exchange).block()).isEqualTo(expected);
}
}
@@ -25,10 +25,13 @@ import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.core.context.SecurityContext;
/**
* A {@link SocketAcceptor} that captures the {@link SecurityContext} and then continues with the {@link RSocket}
* A {@link SocketAcceptor} that captures the {@link SecurityContext} and then continues
* with the {@link RSocket}
*
* @author Rob Winch
*/
class CaptureSecurityContextSocketAcceptor implements SocketAcceptor {
private final RSocket accept;
private SecurityContext securityContext;
@@ -40,11 +43,11 @@ class CaptureSecurityContextSocketAcceptor implements SocketAcceptor {
@Override
public Mono<RSocket> accept(ConnectionSetupPayload setup, RSocket sendingSocket) {
return ReactiveSecurityContextHolder.getContext()
.doOnNext(securityContext -> this.securityContext = securityContext)
.thenReturn(this.accept);
.doOnNext(securityContext -> this.securityContext = securityContext).thenReturn(this.accept);
}
public SecurityContext getSecurityContext() {
return this.securityContext;
}
}
@@ -64,8 +64,8 @@ import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class PayloadInterceptorRSocketTests {
static final MimeType COMPOSITE_METADATA = MimeTypeUtils.parseMimeType(
WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
static final MimeType COMPOSITE_METADATA = MimeTypeUtils
.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
@Mock
RSocket delegate;
@@ -95,26 +95,22 @@ public class PayloadInterceptorRSocketTests {
this.delegate = null;
List<PayloadInterceptor> interceptors = Arrays.asList(this.interceptor);
assertThatCode(() -> {
new PayloadInterceptorRSocket(this.delegate, interceptors,
metadataMimeType, dataMimeType);
})
.isInstanceOf(IllegalArgumentException.class);
new PayloadInterceptorRSocket(this.delegate, interceptors, metadataMimeType, dataMimeType);
}).isInstanceOf(IllegalArgumentException.class);
}
@Test
public void constructorWhenNullInterceptorsThenException() {
List<PayloadInterceptor> interceptors = null;
assertThatCode(() -> new PayloadInterceptorRSocket(this.delegate, interceptors,
metadataMimeType, dataMimeType))
.isInstanceOf(IllegalArgumentException.class);
assertThatCode(() -> new PayloadInterceptorRSocket(this.delegate, interceptors, metadataMimeType, dataMimeType))
.isInstanceOf(IllegalArgumentException.class);
}
@Test
public void constructorWhenEmptyInterceptorsThenException() {
List<PayloadInterceptor> interceptors = Collections.emptyList();
assertThatCode(() -> new PayloadInterceptorRSocket(this.delegate, interceptors,
metadataMimeType, dataMimeType))
.isInstanceOf(IllegalArgumentException.class);
assertThatCode(() -> new PayloadInterceptorRSocket(this.delegate, interceptors, metadataMimeType, dataMimeType))
.isInstanceOf(IllegalArgumentException.class);
}
// single interceptor
@@ -127,9 +123,8 @@ public class PayloadInterceptorRSocketTests {
PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(this.delegate,
Arrays.asList(this.interceptor), metadataMimeType, dataMimeType);
StepVerifier.create(interceptor.fireAndForget(this.payload))
.then(() -> this.voidResult.assertWasSubscribed())
.verifyComplete();
StepVerifier.create(interceptor.fireAndForget(this.payload)).then(() -> this.voidResult.assertWasSubscribed())
.verifyComplete();
verify(this.interceptor).intercept(this.exchange.capture(), any());
assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload);
@@ -144,8 +139,8 @@ public class PayloadInterceptorRSocketTests {
Arrays.asList(this.interceptor), metadataMimeType, dataMimeType);
StepVerifier.create(interceptor.fireAndForget(this.payload))
.then(() -> this.voidResult.assertWasNotSubscribed())
.verifyErrorSatisfies(e -> assertThat(e).isEqualTo(expected));
.then(() -> this.voidResult.assertWasNotSubscribed())
.verifyErrorSatisfies(e -> assertThat(e).isEqualTo(expected));
verify(this.interceptor).intercept(this.exchange.capture(), any());
assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload);
@@ -160,8 +155,7 @@ public class PayloadInterceptorRSocketTests {
RSocket assertAuthentication = new RSocketProxy(this.delegate) {
@Override
public Mono<Void> fireAndForget(Payload payload) {
return assertAuthentication(authentication)
.flatMap(a -> super.fireAndForget(payload));
return assertAuthentication(authentication).flatMap(a -> super.fireAndForget(payload));
}
};
PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(assertAuthentication,
@@ -183,10 +177,8 @@ public class PayloadInterceptorRSocketTests {
Arrays.asList(this.interceptor), metadataMimeType, dataMimeType);
StepVerifier.create(interceptor.requestResponse(this.payload))
.then(() -> this.payloadResult.assertSubscribers())
.then(() -> this.payloadResult.emit(this.payload))
.expectNext(this.payload)
.verifyComplete();
.then(() -> this.payloadResult.assertSubscribers()).then(() -> this.payloadResult.emit(this.payload))
.expectNext(this.payload).verifyComplete();
verify(this.interceptor).intercept(this.exchange.capture(), any());
assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload);
@@ -217,18 +209,15 @@ public class PayloadInterceptorRSocketTests {
RSocket assertAuthentication = new RSocketProxy(this.delegate) {
@Override
public Mono<Payload> requestResponse(Payload payload) {
return assertAuthentication(authentication)
.flatMap(a -> super.requestResponse(payload));
return assertAuthentication(authentication).flatMap(a -> super.requestResponse(payload));
}
};
PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(assertAuthentication,
Arrays.asList(this.interceptor), metadataMimeType, dataMimeType);
StepVerifier.create(interceptor.requestResponse(this.payload))
.then(() -> this.payloadResult.assertSubscribers())
.then(() -> this.payloadResult.emit(this.payload))
.expectNext(this.payload)
.verifyComplete();
.then(() -> this.payloadResult.assertSubscribers()).then(() -> this.payloadResult.emit(this.payload))
.expectNext(this.payload).verifyComplete();
verify(this.interceptor).intercept(this.exchange.capture(), any());
assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload);
@@ -243,11 +232,8 @@ public class PayloadInterceptorRSocketTests {
PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(this.delegate,
Arrays.asList(this.interceptor), metadataMimeType, dataMimeType);
StepVerifier.create(interceptor.requestStream(this.payload))
.then(() -> this.payloadResult.assertSubscribers())
.then(() -> this.payloadResult.emit(this.payload))
.expectNext(this.payload)
.verifyComplete();
StepVerifier.create(interceptor.requestStream(this.payload)).then(() -> this.payloadResult.assertSubscribers())
.then(() -> this.payloadResult.emit(this.payload)).expectNext(this.payload).verifyComplete();
verify(this.interceptor).intercept(this.exchange.capture(), any());
assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload);
@@ -262,8 +248,8 @@ public class PayloadInterceptorRSocketTests {
Arrays.asList(this.interceptor), metadataMimeType, dataMimeType);
StepVerifier.create(interceptor.requestStream(this.payload))
.then(() -> this.payloadResult.assertNoSubscribers())
.verifyErrorSatisfies(e -> assertThat(e).isEqualTo(expected));
.then(() -> this.payloadResult.assertNoSubscribers())
.verifyErrorSatisfies(e -> assertThat(e).isEqualTo(expected));
verify(this.interceptor).intercept(this.exchange.capture(), any());
assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload);
@@ -278,18 +264,14 @@ public class PayloadInterceptorRSocketTests {
RSocket assertAuthentication = new RSocketProxy(this.delegate) {
@Override
public Flux<Payload> requestStream(Payload payload) {
return assertAuthentication(authentication)
.flatMapMany(a -> super.requestStream(payload));
return assertAuthentication(authentication).flatMapMany(a -> super.requestStream(payload));
}
};
PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(assertAuthentication,
Arrays.asList(this.interceptor), metadataMimeType, dataMimeType);
StepVerifier.create(interceptor.requestStream(this.payload))
.then(() -> this.payloadResult.assertSubscribers())
.then(() -> this.payloadResult.emit(this.payload))
.expectNext(this.payload)
.verifyComplete();
StepVerifier.create(interceptor.requestStream(this.payload)).then(() -> this.payloadResult.assertSubscribers())
.then(() -> this.payloadResult.emit(this.payload)).expectNext(this.payload).verifyComplete();
verify(this.interceptor).intercept(this.exchange.capture(), any());
assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload);
@@ -305,10 +287,8 @@ public class PayloadInterceptorRSocketTests {
Arrays.asList(this.interceptor), metadataMimeType, dataMimeType);
StepVerifier.create(interceptor.requestChannel(Flux.just(this.payload)))
.then(() -> this.payloadResult.assertSubscribers())
.then(() -> this.payloadResult.emit(this.payload))
.expectNext(this.payload)
.verifyComplete();
.then(() -> this.payloadResult.assertSubscribers()).then(() -> this.payloadResult.emit(this.payload))
.expectNext(this.payload).verifyComplete();
verify(this.interceptor).intercept(this.exchange.capture(), any());
assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload);
@@ -324,8 +304,8 @@ public class PayloadInterceptorRSocketTests {
Arrays.asList(this.interceptor), this.metadataMimeType, this.dataMimeType);
StepVerifier.create(interceptor.requestChannel(Flux.just(this.payload)))
.then(() -> this.payloadResult.assertNoSubscribers())
.verifyErrorSatisfies(e -> assertThat(e).isEqualTo(expected));
.then(() -> this.payloadResult.assertNoSubscribers())
.verifyErrorSatisfies(e -> assertThat(e).isEqualTo(expected));
verify(this.interceptor).intercept(this.exchange.capture(), any());
assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload);
@@ -341,18 +321,14 @@ public class PayloadInterceptorRSocketTests {
RSocket assertAuthentication = new RSocketProxy(this.delegate) {
@Override
public Flux<Payload> requestChannel(Publisher<Payload> payload) {
return assertAuthentication(authentication)
.flatMapMany(a -> super.requestChannel(payload));
return assertAuthentication(authentication).flatMapMany(a -> super.requestChannel(payload));
}
};
PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(assertAuthentication,
Arrays.asList(this.interceptor), metadataMimeType, dataMimeType);
StepVerifier.create(interceptor.requestChannel(payload))
.then(() -> this.payloadResult.assertSubscribers())
.then(() -> this.payloadResult.emit(this.payload))
.expectNext(this.payload)
.verifyComplete();
StepVerifier.create(interceptor.requestChannel(payload)).then(() -> this.payloadResult.assertSubscribers())
.then(() -> this.payloadResult.emit(this.payload)).expectNext(this.payload).verifyComplete();
verify(this.interceptor).intercept(this.exchange.capture(), any());
assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload);
@@ -367,9 +343,8 @@ public class PayloadInterceptorRSocketTests {
PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(this.delegate,
Arrays.asList(this.interceptor), metadataMimeType, dataMimeType);
StepVerifier.create(interceptor.metadataPush(this.payload))
.then(() -> this.voidResult.assertWasSubscribed())
.verifyComplete();
StepVerifier.create(interceptor.metadataPush(this.payload)).then(() -> this.voidResult.assertWasSubscribed())
.verifyComplete();
verify(this.interceptor).intercept(this.exchange.capture(), any());
assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload);
@@ -383,9 +358,8 @@ public class PayloadInterceptorRSocketTests {
PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(this.delegate,
Arrays.asList(this.interceptor), metadataMimeType, dataMimeType);
StepVerifier.create(interceptor.metadataPush(this.payload))
.then(() -> this.voidResult.assertWasNotSubscribed())
.verifyErrorSatisfies(e -> assertThat(e).isEqualTo(expected));
StepVerifier.create(interceptor.metadataPush(this.payload)).then(() -> this.voidResult.assertWasNotSubscribed())
.verifyErrorSatisfies(e -> assertThat(e).isEqualTo(expected));
verify(this.interceptor).intercept(this.exchange.capture(), any());
assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload);
@@ -400,15 +374,13 @@ public class PayloadInterceptorRSocketTests {
RSocket assertAuthentication = new RSocketProxy(this.delegate) {
@Override
public Mono<Void> metadataPush(Payload payload) {
return assertAuthentication(authentication)
.flatMap(a -> super.metadataPush(payload));
return assertAuthentication(authentication).flatMap(a -> super.metadataPush(payload));
}
};
PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(assertAuthentication,
Arrays.asList(this.interceptor), metadataMimeType, dataMimeType);
StepVerifier.create(interceptor.metadataPush(this.payload))
.verifyComplete();
StepVerifier.create(interceptor.metadataPush(this.payload)).verifyComplete();
verify(this.interceptor).intercept(this.exchange.capture(), any());
assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload);
@@ -425,8 +397,7 @@ public class PayloadInterceptorRSocketTests {
when(this.delegate.fireAndForget(any())).thenReturn(this.voidResult.mono());
PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(this.delegate,
Arrays.asList(this.interceptor, this.interceptor2), metadataMimeType,
dataMimeType);
Arrays.asList(this.interceptor, this.interceptor2), metadataMimeType, dataMimeType);
interceptor.fireAndForget(this.payload).block();
@@ -435,7 +406,6 @@ public class PayloadInterceptorRSocketTests {
this.voidResult.assertWasSubscribed();
}
@Test
public void fireAndForgetWhenInterceptorsMutatesPayloadThenDelegateInvoked() {
when(this.interceptor.intercept(any(), any())).thenAnswer(withChainNext());
@@ -443,8 +413,7 @@ public class PayloadInterceptorRSocketTests {
when(this.delegate.fireAndForget(any())).thenReturn(this.voidResult.mono());
PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(this.delegate,
Arrays.asList(this.interceptor, this.interceptor2), metadataMimeType,
dataMimeType);
Arrays.asList(this.interceptor, this.interceptor2), metadataMimeType, dataMimeType);
interceptor.fireAndForget(this.payload).block();
@@ -461,8 +430,7 @@ public class PayloadInterceptorRSocketTests {
when(this.interceptor.intercept(any(), any())).thenReturn(Mono.error(expected));
PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(this.delegate,
Arrays.asList(this.interceptor, this.interceptor2), metadataMimeType,
dataMimeType);
Arrays.asList(this.interceptor, this.interceptor2), metadataMimeType, dataMimeType);
assertThatCode(() -> interceptor.fireAndForget(this.payload).block()).isEqualTo(expected);
@@ -479,8 +447,7 @@ public class PayloadInterceptorRSocketTests {
when(this.interceptor2.intercept(any(), any())).thenReturn(Mono.error(expected));
PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(this.delegate,
Arrays.asList(this.interceptor, this.interceptor2), metadataMimeType,
dataMimeType);
Arrays.asList(this.interceptor, this.interceptor2), metadataMimeType, dataMimeType);
assertThatCode(() -> interceptor.fireAndForget(this.payload).block()).isEqualTo(expected);
@@ -491,16 +458,15 @@ public class PayloadInterceptorRSocketTests {
}
private Mono<Authentication> assertAuthentication(Authentication authentication) {
return ReactiveSecurityContextHolder.getContext()
.map(SecurityContext::getAuthentication)
return ReactiveSecurityContextHolder.getContext().map(SecurityContext::getAuthentication)
.doOnNext(a -> assertThat(a).isEqualTo(authentication));
}
private Answer<Object> withAuthenticated(Authentication authentication) {
return invocation -> {
PayloadInterceptorChain c = (PayloadInterceptorChain) invocation.getArguments()[1];
return c.next(new DefaultPayloadExchange(PayloadExchangeType.REQUEST_CHANNEL, this.payload, this.metadataMimeType,
this.dataMimeType))
return c.next(new DefaultPayloadExchange(PayloadExchangeType.REQUEST_CHANNEL, this.payload,
this.metadataMimeType, this.dataMimeType))
.subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication));
};
}
@@ -512,4 +478,5 @@ public class PayloadInterceptorRSocketTests {
return chain.next(exchange);
};
}
}
@@ -48,6 +48,7 @@ import static org.mockito.Mockito.when;
*/
@RunWith(MockitoJUnitRunner.class)
public class PayloadSocketAcceptorInterceptorTests {
@Mock
private PayloadInterceptor interceptor;
@@ -79,7 +80,8 @@ public class PayloadSocketAcceptorInterceptorTests {
PayloadExchange exchange = captureExchange();
assertThat(exchange.getMetadataMimeType().toString()).isEqualTo(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
assertThat(exchange.getMetadataMimeType().toString())
.isEqualTo(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
assertThat(exchange.getDataMimeType()).isEqualTo(MediaType.APPLICATION_JSON);
}
@@ -100,7 +102,8 @@ public class PayloadSocketAcceptorInterceptorTests {
PayloadExchange exchange = captureExchange();
assertThat(exchange.getMetadataMimeType().toString()).isEqualTo(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
assertThat(exchange.getMetadataMimeType().toString())
.isEqualTo(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
assertThat(exchange.getDataMimeType()).isEqualTo(MediaType.APPLICATION_JSON);
}
@@ -117,9 +120,9 @@ public class PayloadSocketAcceptorInterceptorTests {
result.fireAndForget(this.payload).block();
ArgumentCaptor<PayloadExchange> exchangeArg =
ArgumentCaptor.forClass(PayloadExchange.class);
ArgumentCaptor<PayloadExchange> exchangeArg = ArgumentCaptor.forClass(PayloadExchange.class);
verify(this.interceptor, times(2)).intercept(exchangeArg.capture(), any());
return exchangeArg.getValue();
}
}
@@ -100,8 +100,8 @@ public class PayloadSocketAcceptorTests {
@Test
public void acceptWhenDataMimeTypeNullThenException() {
assertThatCode(() -> this.acceptor.accept(this.setupPayload, this.rSocket)
.block()).isInstanceOf(IllegalArgumentException.class);
assertThatCode(() -> this.acceptor.accept(this.setupPayload, this.rSocket).block())
.isInstanceOf(IllegalArgumentException.class);
}
@Test
@@ -132,8 +132,8 @@ public class PayloadSocketAcceptorTests {
PayloadExchange exchange = captureExchange();
assertThat(exchange.getMetadataMimeType()
.toString()).isEqualTo(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
assertThat(exchange.getMetadataMimeType().toString())
.isEqualTo(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
assertThat(exchange.getDataMimeType()).isEqualTo(MediaType.APPLICATION_JSON);
}
@@ -148,18 +148,19 @@ public class PayloadSocketAcceptorTests {
assertThat(exchange.getDataMimeType()).isEqualTo(MediaType.APPLICATION_JSON);
}
@Test
// gh-8654
public void acceptWhenDelegateAcceptRequiresReactiveSecurityContext() {
when(this.setupPayload.metadataMimeType()).thenReturn(MediaType.TEXT_PLAIN_VALUE);
when(this.setupPayload.dataMimeType()).thenReturn(MediaType.APPLICATION_JSON_VALUE);
SecurityContext expectedSecurityContext = new SecurityContextImpl(new TestingAuthenticationToken("user", "password", "ROLE_USER"));
CaptureSecurityContextSocketAcceptor captureSecurityContext = new CaptureSecurityContextSocketAcceptor(this.rSocket);
SecurityContext expectedSecurityContext = new SecurityContextImpl(
new TestingAuthenticationToken("user", "password", "ROLE_USER"));
CaptureSecurityContextSocketAcceptor captureSecurityContext = new CaptureSecurityContextSocketAcceptor(
this.rSocket);
PayloadInterceptor authenticateInterceptor = (exchange, chain) -> {
Context withSecurityContext = ReactiveSecurityContextHolder.withSecurityContext(Mono.just(expectedSecurityContext));
return chain.next(exchange)
.subscriberContext(withSecurityContext);
Context withSecurityContext = ReactiveSecurityContextHolder
.withSecurityContext(Mono.just(expectedSecurityContext));
return chain.next(exchange).subscriberContext(withSecurityContext);
};
List<PayloadInterceptor> interceptors = Arrays.asList(authenticateInterceptor);
this.acceptor = new PayloadSocketAcceptor(captureSecurityContext, interceptors);
@@ -181,9 +182,9 @@ public class PayloadSocketAcceptorTests {
result.fireAndForget(this.payload).block();
ArgumentCaptor<PayloadExchange> exchangeArg =
ArgumentCaptor.forClass(PayloadExchange.class);
ArgumentCaptor<PayloadExchange> exchangeArg = ArgumentCaptor.forClass(PayloadExchange.class);
verify(this.interceptor, times(2)).intercept(exchangeArg.capture(), any());
return exchangeArg.getValue();
}
}
@@ -31,20 +31,18 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Rob Winch
*/
public class BasicAuthenticationDecoderTests {
@Test
public void basicAuthenticationWhenEncodedThenDecodes() {
BasicAuthenticationEncoder encoder = new BasicAuthenticationEncoder();
BasicAuthenticationDecoder decoder = new BasicAuthenticationDecoder();
UsernamePasswordMetadata expectedCredentials =
new UsernamePasswordMetadata("rob", "password");
UsernamePasswordMetadata expectedCredentials = new UsernamePasswordMetadata("rob", "password");
DefaultDataBufferFactory factory = new DefaultDataBufferFactory();
ResolvableType elementType = ResolvableType
.forClass(UsernamePasswordMetadata.class);
ResolvableType elementType = ResolvableType.forClass(UsernamePasswordMetadata.class);
MimeType mimeType = UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE;
Map<String, Object> hints = null;
DataBuffer dataBuffer = encoder.encodeValue(expectedCredentials, factory,
elementType, mimeType, hints);
DataBuffer dataBuffer = encoder.encodeValue(expectedCredentials, factory, elementType, mimeType, hints);
UsernamePasswordMetadata actualCredentials = decoder
.decodeToMono(Mono.just(dataBuffer), elementType, mimeType, hints).block();
@@ -44,8 +44,9 @@ import static org.mockito.Mockito.when;
*/
@RunWith(MockitoJUnitRunner.class)
public class RoutePayloadExchangeMatcherTests {
static final MimeType COMPOSITE_METADATA = MimeTypeUtils.parseMimeType(
WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
static final MimeType COMPOSITE_METADATA = MimeTypeUtils
.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
@Mock
private MetadataExtractor metadataExtractor;
@@ -69,14 +70,13 @@ public class RoutePayloadExchangeMatcherTests {
public void setup() {
this.pattern = "a.b";
this.matcher = new RoutePayloadExchangeMatcher(this.metadataExtractor, this.routeMatcher, this.pattern);
this.exchange = new DefaultPayloadExchange(PayloadExchangeType.REQUEST_CHANNEL, this.payload, COMPOSITE_METADATA,
MediaType.APPLICATION_JSON);
this.exchange = new DefaultPayloadExchange(PayloadExchangeType.REQUEST_CHANNEL, this.payload,
COMPOSITE_METADATA, MediaType.APPLICATION_JSON);
}
@Test
public void matchesWhenNoRouteThenNotMatch() {
when(this.metadataExtractor.extract(any(), any()))
.thenReturn(Collections.emptyMap());
when(this.metadataExtractor.extract(any(), any())).thenReturn(Collections.emptyMap());
PayloadExchangeMatcher.MatchResult result = this.matcher.matches(this.exchange).block();
assertThat(result.isMatch()).isFalse();
}
@@ -113,4 +113,5 @@ public class RoutePayloadExchangeMatcherTests {
assertThat(result.isMatch()).isTrue();
assertThat(result.getVariables()).containsAllEntriesOf(variables);
}
}