我正在构建一个服务,它将允许用户将多个oauth身份与他们的帐户相关联,然后根据任何/所有身份检索信息。
我使用Spring提供的R2dbcReactiveOAuth2AuthorizedClientService
将oauth身份存储在Postgres中。我目前的挑战是将保存的Oauth标识关联到WebClient,以便信息基于该Oauth标识。
基于ServerOAuth2AuthorizedClientExchangeFilterFunction.oauth2AuthorizedClient
的JavaDoc,我可以传递OAuth2AuthorizedClient
,它将对WebClient.retrieve()
使用该标识。
修改ClientRequest.attributes()以包含用于提供承载令牌的OAuth2 AuthorizedClient。示例用法:
WebClient webClient = WebClient.builder()
.filter(new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager))
.build();
Mono<String> response = webClient
.get()
.uri(uri)
.attributes(oauth2AuthorizedClient(authorizedClient))
// ...
.retrieve()
.bodyToMono(String.class);
基于调试,我当前的代码成功地从数据库加载了oauth标识,并将其作为属性添加到WebClient。当WebClient检索时,我得到错误IllegalArgumentException: serverWebExchange cannot be null
。SO上的其他问题涉及到这个错误,表明当您混合使用servlet和响应式调用时会发生这个错误。然而,我只有WebFlux作为maven依赖项,所以我很确定这里不会发生这种情况。
关于如何解决/继续的任何建议?
我的产品服务
public class ProductService {
private final ReactiveOAuth2AuthorizedClientService oAuth2AuthorizedClientService;
private final ReactiveClientRegistrationRepository clientRegistrations;
private static final String baseUri = "https://myapp.net/product";
public ProductService(ReactiveOAuth2AuthorizedClientService oAuth2AuthorizedClientService,
ReactiveClientRegistrationRepository clientRegistrations) {
this.oAuth2AuthorizedClientService = oAuth2AuthorizedClientService;
this.clientRegistrations = clientRegistrations;
}
public Mono<String> getNotifications(String productName, String userName) {
String dataUri = "/{id}/notifications";
Mono<OAuth2AuthorizedClient> userOauth = oAuth2AuthorizedClientService.loadAuthorizedClient("xxx", userName);
Mono<Long> productId = this.lookupProductId(productName);
return Mono.zip(productId, userOauth).checkpoint().flatMap(tuple2 ->
this.getUserWebClient(userName).get()
.uri(uriBuilder -> uriBuilder
.path(dataUri)
.queryParam("datasource", "development")
.build(tuple2.getT1().toString()))
.attributes(ServerOAuth2AuthorizedClientExchangeFilterFunction.oauth2AuthorizedClient(tuple2.getT2()))
.retrieve()
.bodyToMono(String.class));
}
private WebClient getUserWebClient() {
var authorizedClients = new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository(oAuth2AuthorizedClientService);
var oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
clientRegistrations, authorizedClients);
return WebClient.builder()
.baseUrl(baseUri)
.filter(oauth)
.build();
}
public Mono<Long> lookupProductId(String name) {
// business logic to lookup product based on name
}
}
Web安全配置使用Postgres存储库而不是默认的In-Memory bean
@Bean
public ReactiveOAuth2AuthorizedClientService dbOauth2AuthorizedClientService(DatabaseClient databaseClient,
ReactiveClientRegistrationRepository clientRegistrationRepository) {
return new R2dbcReactiveOAuth2AuthorizedClientService(databaseClient, clientRegistrationRepository);
}
1条答案
按热度按时间t1rydlwq1#
在度过了一个愉快的暑假后,我在https://docs.spring.io/spring-security/reference/reactive/oauth2/client/core.html上找到并重新阅读了文档。这让我明白错误是由于没有
ResponseContext
,因为它在@Service
组件中。暂时,我把它移到了一个@Controller
中的一个@GetMapping
。文档指出
AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager
可以用于@Service
组件。我将尝试更新这个答案的代码,一旦我有它完成。