Makes dependencies of TokenRelayGatewayFilterFactory lazy.

Because of the use in the java dsl before oauth2 client auto configuration can run, the ReactiveOAuth2AuthorizedClientManager field of TokenRelayGatewayFilterFactory needs to be lazy.
This commit is contained in:
spencergibb
2020-11-10 12:57:11 -05:00
parent b0b77ce83c
commit 8722f4062e
3 changed files with 17 additions and 6 deletions

View File

@@ -845,16 +845,16 @@ public class GatewayAutoConfiguration {
@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true)
@ConditionalOnClass({ OAuth2AuthorizedClient.class, SecurityWebFilterChain.class, SecurityProperties.class })
@ConditionalOnEnabledFilter(TokenRelayGatewayFilterFactory.class)
@ConditionalOnBean(ReactiveClientRegistrationRepository.class)
protected static class TokenRelayConfiguration {
@Bean
public TokenRelayGatewayFilterFactory tokenRelayGatewayFilterFactory(
ReactiveOAuth2AuthorizedClientManager clientManager) {
ObjectProvider<ReactiveOAuth2AuthorizedClientManager> clientManager) {
return new TokenRelayGatewayFilterFactory(clientManager);
}
@Bean
@ConditionalOnBean(ReactiveClientRegistrationRepository.class)
public ReactiveOAuth2AuthorizedClientManager gatewayReactiveOAuth2AuthorizedClientManager(
ReactiveClientRegistrationRepository clientRegistrationRepository,
ServerOAuth2AuthorizedClientRepository authorizedClientRepository) {

View File

@@ -18,6 +18,7 @@ package org.springframework.cloud.gateway.filter.factory;
import reactor.core.publisher.Mono;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
@@ -31,11 +32,11 @@ import org.springframework.web.server.ServerWebExchange;
*/
public class TokenRelayGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {
private final ReactiveOAuth2AuthorizedClientManager clientManager;
private final ObjectProvider<ReactiveOAuth2AuthorizedClientManager> clientManagerProvider;
public TokenRelayGatewayFilterFactory(ReactiveOAuth2AuthorizedClientManager clientManager) {
public TokenRelayGatewayFilterFactory(ObjectProvider<ReactiveOAuth2AuthorizedClientManager> clientManagerProvider) {
super(Object.class);
this.clientManager = clientManager;
this.clientManagerProvider = clientManagerProvider;
}
public GatewayFilter apply() {
@@ -59,6 +60,12 @@ public class TokenRelayGatewayFilterFactory extends AbstractGatewayFilterFactory
String clientRegistrationId = oauth2Authentication.getAuthorizedClientRegistrationId();
OAuth2AuthorizeRequest request = OAuth2AuthorizeRequest.withClientRegistrationId(clientRegistrationId)
.principal(oauth2Authentication).build();
ReactiveOAuth2AuthorizedClientManager clientManager = clientManagerProvider.getIfAvailable();
if (clientManager == null) {
return Mono.error(
new IllegalStateException("No ReactiveOAuth2AuthorizedClientManager bean was found. Did you include the "
+ "org.springframework.boot:spring-boot-starter-oauth2-client dependency?"));
}
// TODO: use Mono.defer() for request above?
return clientManager.authorize(request);
}

View File

@@ -24,6 +24,7 @@ import org.junit.Before;
import org.junit.Test;
import reactor.core.publisher.Mono;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.http.HttpHeaders;
@@ -69,6 +70,7 @@ public class TokenRelayGatewayFilterFactoryTests {
}
@Before
@SuppressWarnings("unchecked")
public void init() {
request = MockServerHttpRequest.get("/hello").build();
mockExchange = MockServerWebExchange.from(request);
@@ -76,7 +78,9 @@ public class TokenRelayGatewayFilterFactoryTests {
when(filterChain.filter(any(ServerWebExchange.class))).thenReturn(Mono.empty());
authorizedClientManager = mock(ReactiveOAuth2AuthorizedClientManager.class);
filter = new TokenRelayGatewayFilterFactory(authorizedClientManager).apply();
ObjectProvider<ReactiveOAuth2AuthorizedClientManager> objectProvider = mock(ObjectProvider.class);
when(objectProvider.getIfAvailable()).thenReturn(authorizedClientManager);
filter = new TokenRelayGatewayFilterFactory(objectProvider).apply();
}
@After