Spring MVC имеет много разумных значений по умолчанию, которых нет в WebFlux.Это один из них.
Я решил эту проблему, настроив WebFilter, который принимает токены в строке запроса и добавляет их в заголовок.
@Override
@NonNull
public Mono<Void> filter(
@NonNull ServerWebExchange serverWebExchange, @NonNull WebFilterChain
webFilterChain) {
ServerHttpRequest request = serverWebExchange.getRequest();
return webFilterChain.filter(
serverWebExchange.mutate().request(sanitizeRequest(request)).build());
}
private ServerHttpRequest sanitizeRequest(ServerHttpRequest request) {
MultiValueMap<String, String> queryParams = request.getQueryParams();
ServerHttpRequest.Builder newRequest =
request
.mutate()
.headers(
headers -> {
if (headerContainsAuthorizationKey(headers)) {
String token = getAuthorizationBearer(headers);
if (token != null) {
// "bearer" breaks WebFlux OAuth :)
headers.set(HttpHeaders.AUTHORIZATION, token.replace("bearer", "Bearer"));
return;
}
}
if (pathContainsAccessToken(queryParams)) {
headers.set(
HttpHeaders.AUTHORIZATION,
"Bearer " + queryParams.getFirst("access_token"));
}
});
if (pathContainsAccessToken(queryParams)) {
newRequest.uri(buildNewUriWithoutToken(request.getURI(), queryParams));
}
return newRequest.build();
}
}
Приятно отметить, чтострочный «переносчик» также нарушает работу WebFlux.
После этого вы можете добавить этот фильтр прямо перед вашей спецификацией oauthResourceServer в цепочке безопасности:
@Bean
public SecurityWebFilterChain springSecurityFilterChain(
ServerHttpSecurity http,
TokenStore tokenStore,
AuthorizationHeaderFilter authorizationHeaderFilter) {
http.csrf()
.disable()
.authorizeExchange()
.anyExchange()
.authenticated()
.and()
.addFilterAt(authorizationHeaderFilter, SecurityWebFiltersOrder.FIRST)
.oauth2ResourceServer()
.jwt() // ... etc
return http.build();
}