SpringWebFlux:redirectUriTemplate的断言不为null,即使我使用的是OAuth2.0客户端凭据
我将Spring Boot 2.2.4与SpringWebFlux:redirectUriTemplate的断言不为null,即使我使用的是OAuth2.0客户端凭据,spring,spring-boot,oauth-2.0,spring-webflux,clientcredential,Spring,Spring Boot,Oauth 2.0,Spring Webflux,Clientcredential,我将Spring Boot 2.2.4与Spring Boot starter webflux、Spring Boot starter security和Spring-security-oauth2-client一起使用 我想用被动的方式打电话给using,获取一些用户信息 我跟着。我的application.properties如下所示: spring.security.oauth2.client.registration.auth0.authorization-grant-type=clie
Spring Boot starter webflux
、Spring Boot starter security
和Spring-security-oauth2-client
一起使用
我想用被动的方式打电话给using,获取一些用户信息
我跟着。我的application.properties
如下所示:
spring.security.oauth2.client.registration.auth0.authorization-grant-type=client_credentials
spring.security.oauth2.client.registration.auth0.client-id=XXX
spring.security.oauth2.client.registration.auth0.client-secret=YYY
spring.security.oauth2.client.provider.auth0.token-uri=https://ZZZ.eu.auth0.com/oauth/token
@Configuration
@RequiredArgsConstructor
class Auth0Configuration {
@Value("${auth0.api.base-url}")
private final String auth0ApiBaseUrl;
@Bean
WebClient auth0WebClient(ReactiveClientRegistrationRepository reactiveClientRegistrationRepository) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth =
new ServerOAuth2AuthorizedClientExchangeFilterFunction(
reactiveClientRegistrationRepository,
new UnAuthenticatedServerOAuth2AuthorizedClientRepository());
oauth.setDefaultClientRegistrationId("auth0");
return WebClient.builder()
.filter(oauth)
.baseUrl(auth0ApiBaseUrl)
.build();
}
}
我的Spring@配置如下:
spring.security.oauth2.client.registration.auth0.authorization-grant-type=client_credentials
spring.security.oauth2.client.registration.auth0.client-id=XXX
spring.security.oauth2.client.registration.auth0.client-secret=YYY
spring.security.oauth2.client.provider.auth0.token-uri=https://ZZZ.eu.auth0.com/oauth/token
@Configuration
@RequiredArgsConstructor
class Auth0Configuration {
@Value("${auth0.api.base-url}")
private final String auth0ApiBaseUrl;
@Bean
WebClient auth0WebClient(ReactiveClientRegistrationRepository reactiveClientRegistrationRepository) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth =
new ServerOAuth2AuthorizedClientExchangeFilterFunction(
reactiveClientRegistrationRepository,
new UnAuthenticatedServerOAuth2AuthorizedClientRepository());
oauth.setDefaultClientRegistrationId("auth0");
return WebClient.builder()
.filter(oauth)
.baseUrl(auth0ApiBaseUrl)
.build();
}
}
但是,当我使用WebClient
进行第一次调用时,会发生以下错误:
2020-02-12 20:18:11.098 ERROR 1945 --- [ctor-http-nio-3] a.w.r.e.AbstractErrorWebExceptionHandler : [f0218135] 500 Server Error for HTTP GET "/oauth2/authorization/auth0"
java.lang.IllegalArgumentException: URI must not be null
at org.springframework.util.Assert.notNull(Assert.java:198)
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ org.springframework.security.oauth2.client.web.server.OAuth2AuthorizationRequestRedirectWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.context.ReactorContextWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.csrf.CsrfWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.header.HttpHeaderWriterWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ HTTP GET "/oauth2/authorization/auth0" [ExceptionHandlingWebHandler]
Stack trace:
at org.springframework.util.Assert.notNull(Assert.java:198)
at org.springframework.web.util.UriComponentsBuilder.fromUriString(UriComponentsBuilder.java:212)
at org.springframework.security.oauth2.client.web.server.DefaultServerOAuth2AuthorizationRequestResolver.expandRedirectUri(DefaultServerOAuth2AuthorizationRequestResolver.java:214)
at org.springframework.security.oauth2.client.web.server.DefaultServerOAuth2AuthorizationRequestResolver.authorizationRequest(DefaultServerOAuth2AuthorizationRequestResolver.java:131)
at org.springframework.security.oauth2.client.web.server.DefaultServerOAuth2AuthorizationRequestResolver.lambda$resolve$3(DefaultServerOAuth2AuthorizationRequestResolver.java:121)
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:100)
at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:67)
at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2199)
at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:2007)
at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:1881)
at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:55)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:150)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:121)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:121)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:121)
at reactor.core.publisher.FluxFilterFuseable$FilterFuseableSubscriber.onNext(FluxFilterFuseable.java:112)
at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2199)
at reactor.core.publisher.FluxFilterFuseable$FilterFuseableSubscriber.request(FluxFilterFuseable.java:184)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:162)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:162)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:162)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onSubscribe(MonoFlatMap.java:103)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:90)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:90)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:90)
at reactor.core.publisher.FluxFilterFuseable$FilterFuseableSubscriber.onSubscribe(FluxFilterFuseable.java:81)
at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:55)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:55)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.Mono.subscribe(Mono.java:4105)
at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:172)
at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56)
at reactor.core.publisher.Mono.subscribe(Mono.java:4105)
at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onComplete(FluxSwitchIfEmpty.java:75)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onComplete(MonoFlatMap.java:174)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onComplete(MonoFlatMap.java:174)
at reactor.core.publisher.FluxFilter$FilterSubscriber.onComplete(FluxFilter.java:160)
at reactor.core.publisher.FluxFilter$FilterConditionalSubscriber.onComplete(FluxFilter.java:293)
at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onComplete(FluxSwitchIfEmpty.java:78)
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1638)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:144)
at reactor.core.publisher.FluxFilterFuseable$FilterFuseableSubscriber.onNext(FluxFilterFuseable.java:112)
at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onNext(FluxMapFuseable.java:287)
at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2199)
at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.request(FluxMapFuseable.java:346)
at reactor.core.publisher.FluxFilterFuseable$FilterFuseableSubscriber.request(FluxFilterFuseable.java:184)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onSubscribe(MonoFlatMap.java:103)
at reactor.core.publisher.FluxFilterFuseable$FilterFuseableSubscriber.onSubscribe(FluxFilterFuseable.java:81)
at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onSubscribe(FluxMapFuseable.java:255)
at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:55)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:55)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:55)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:150)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:121)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:121)
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1637)
at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:241)
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1637)
at reactor.core.publisher.MonoCollectList$MonoCollectListSubscriber.onComplete(MonoCollectList.java:121)
at reactor.core.publisher.FluxIterable$IterableSubscription.fastPath(FluxIterable.java:333)
at reactor.core.publisher.FluxIterable$IterableSubscription.request(FluxIterable.java:198)
at reactor.core.publisher.MonoCollectList$MonoCollectListSubscriber.onSubscribe(MonoCollectList.java:72)
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:139)
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:63)
at reactor.core.publisher.MonoFromFluxOperator.subscribe(MonoFromFluxOperator.java:72)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:150)
at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:67)
at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76)
at reactor.core.publisher.FluxFilterWhen$FluxFilterWhenSubscriber.drain(FluxFilterWhen.java:295)
at reactor.core.publisher.FluxFilterWhen$FluxFilterWhenSubscriber.onNext(FluxFilterWhen.java:134)
at reactor.core.publisher.FluxIterable$IterableSubscription.slowPath(FluxIterable.java:243)
at reactor.core.publisher.FluxIterable$IterableSubscription.request(FluxIterable.java:201)
at reactor.core.publisher.FluxFilterWhen$FluxFilterWhenSubscriber.onSubscribe(FluxFilterWhen.java:194)
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:139)
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:63)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:55)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:55)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:55)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.Mono.subscribe(Mono.java:4105)
at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:172)
at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:55)
at reactor.netty.http.server.HttpServerHandle.onStateChange(HttpServerHandle.java:64)
at reactor.netty.tcp.TcpServerBind$ChildObserver.onStateChange(TcpServerBind.java:228)
at reactor.netty.http.server.HttpServerOperations.onInboundNext(HttpServerOperations.java:465)
at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:90)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:355)
at reactor.netty.http.server.HttpTrafficHandler.channelRead(HttpTrafficHandler.java:167)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:355)
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:321)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:295)
at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:355)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:830)
在跟踪堆栈跟踪时,我看到中的属性redirectUriTemplate
为null
。但由于我使用的是客户端凭据,所以根本不需要重定向URI
我的配置中有错误吗?如何使WebClient
与客户端凭据流一起工作?应用程序现在正在使用此配置:
@Configuration
@RequiredArgsConstructor
@Slf4j
class Auth0Configuration {
// some properties
@Bean
WebClient auth0WebClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
var exchangeFilterFunction = new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
exchangeFilterFunction.setDefaultClientRegistrationId(AUTH_0_CLIENT_REGISTRATION_ID);
return WebClient.builder()
.baseUrl(auth0ApiBaseUrl)
.filter(exchangeFilterFunction)
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.build();
}
@Bean
public ReactiveClientRegistrationRepository reactiveClientRegistrationRepository() {
return new InMemoryReactiveClientRegistrationRepository(
ClientRegistration.withRegistrationId(AUTH_0_CLIENT_REGISTRATION_ID)
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.tokenUri(auth0TokenUri)
.clientAuthenticationMethod(ClientAuthenticationMethod.POST)
.clientId(auth0ClientId)
.clientSecret(auth0ClientSecret)
.scope()
.build()
);
}
@Bean
public ReactiveOAuth2AuthorizedClientManager reactiveOAuth2AuthorizedClientManager(ReactiveClientRegistrationRepository clientRegistrationRepository) {
DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultReactiveOAuth2AuthorizedClientManager(clientRegistrationRepository, new UnAuthenticatedServerOAuth2AuthorizedClientRepository());
authorizedClientManager.setAuthorizedClientProvider(ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials(clientCredentialsGrantBuilder -> {
WebClientReactiveClientCredentialsTokenResponseClient accessTokenResponseClient = new WebClientReactiveClientCredentialsTokenResponseClient();
accessTokenResponseClient.setWebClient(WebClient.builder()
.filter((request, next) -> {
FormInserter<String> body = (FormInserter<String>) request.body();
body.with("audience", auth0Audience);
return next.exchange(request);
})
.build());
clientCredentialsGrantBuilder.accessTokenResponseClient(accessTokenResponseClient);
}
)
.build()
);
return authorizedClientManager;
}
}
@配置
@所需参数构造函数
@Slf4j
类auth0配置{
//一些性质
@豆子
WebClient auth0WebClient(reactiveOAuth2AuthorizedClient管理器AuthorizedClient管理器){
var exchangeFilterFunction=新服务器OAuth2AuthorizedClientChangeFilterFunction(authorizedClientManager);
exchangeFilterFunction.setDefaultClientRegistrationId(身份验证0客户端注册ID);
返回WebClient.builder()
.baseUrl(auth0ApiBaseUrl)
.filter(ExchangeFilter函数)
.defaultHeader(HttpHeaders.CONTENT\u TYPE、MediaType.APPLICATION\u JSON\u值)
.build();
}
@豆子
public ReactiveClientRegistrationRepository ReactiveClientRegistrationRepository(){
返回新的InMemoryReactiveClientRegistrationRepository(
ClientRegistration.withRegistrationId(身份验证\u 0\u客户端\u注册\u ID)
.authorizationGrantType(authorizationGrantType.CLIENT\u凭据)
.tokenUri(auth0TokenUri)
.clientAuthenticationMethod(clientAuthenticationMethod.POST)
.clientId(auth0ClientId)
.clientSecret(auth0ClientSecret)
.scope()
.build()
);
}
@豆子
public ReactiveOAuth2AuthorizedClientManager ReactiveOAuth2AuthorizedClientManager(ReactiveClientRegistrationRepository clientRegistrationRepository){
DefaultReactiveOAuth2AuthorizedClientManager授权dClientManager=
新的DefaultReactiveOAuth2AuthorizedClientManager(clientRegistrationRepository,新的未经身份验证的服务器OAuth2AuthorizedClientRepository());
authorizedClientManager.setAuthorizedClientProvider(ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials(clientCredentialsGrantBuilder->{
WebClientStreamActiveClientCredentialsTokenResponseClient访问TokenResponseClient=新的WebClientStreamActiveClientCredentialsTokenResponseClient();
accessTokenResponseClient.setWebClient(WebClient.builder())
.filter((请求,下一步)->{
FormInserter body=(FormInserter)request.body();
body.with(“观众”,auth0观众);
下一步返回。交换(请求);
})
.build());
clientCredentialsGrantBuilder.accessTokenResponseClient(accessTokenResponseClient);
}
)
.build()
);
返回授权客户管理器;
}
}
@Value(${auth0.api.base url}”)
这在您的应用程序中是什么样子的。properties
@thomasand如果这是我请求的基本url的值。它解析为。spring.security.oauth2.client.provider.auth0.token uri
我在任何地方都找不到此参数存在。我意识到我必须删除库“org.springframework.boot:spring boot starter security”“从gradle文件中,一切都很顺利。我们只需要“org.springframework.security:spring-security-oauth2-client”和Harold L.Brown解决方案中的前两个方法。