21. WebClient
Note
以下文档供在 Reactive 环境中使用。对于 Servlet 环境,请参考Servlet 的 WebClient环境。
Spring Framework 内置了对设置 Bearer 令牌的支持。
webClient.get()
.headers(h -> h.setBearerAuth(token))
...
Spring Security 在此支持的基础上提供了其他好处:
-
Spring Security 将自动刷新过期的令牌(如果存在刷新令牌)
-
如果请求访问令牌但不存在,则 Spring Security 将自动请求访问令牌。
-
对于 authorization_code,这涉及执行重定向,然后重播原始请求
- 对于 client_credentials,只需请求并保存令牌
-
支持透明包含当前 OAuth 令牌或明确选择应使用的令牌的功能。
21.1 WebClient OAuth2 设置
第一步是确保正确设置WebClient
。在完全反应的环境中设置WebClient
的示例如下:
@Bean
WebClient webClient(ReactiveClientRegistrationRepository clientRegistrations,
ServerOAuth2AuthorizedClientRepository authorizedClients) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth =
new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, authorizedClients);
// (optional) explicitly opt into using the oauth2Login to provide an access token implicitly
// oauth.setDefaultOAuth2AuthorizedClient(true);
// (optional) set a default ClientRegistration.registrationId
// oauth.setDefaultClientRegistrationId("client-registration-id");
return WebClient.builder()
.filter(oauth)
.build();
}
21.2 隐式 OAuth2AuthorizedClient
如果我们将defaultOAuth2AuthorizedClient
设置为有效的ClientRegistration
id 的true
in our setup and the user authenticated with oauth2Login (i.e. OIDC), then the current authentication is used to automatically provide the access token. Alternatively, if we set defaultClientRegistrationId
,则该注册将用于提供访问令牌。这很方便,但是在并非所有端点都应获取访问令牌的环境中,这样做很危险(您可能为端点提供了错误的访问令牌)。
Mono<String> body = this.webClient
.get()
.uri(this.uri)
.retrieve()
.bodyToMono(String.class);
21.3 显式 OAuth2AuthorizedClient
OAuth2AuthorizedClient
可以通过在请求属性上设置来明确提供。在下面的示例中,我们使用 Spring WebFlux 或 Spring MVC 参数解析器支持来解析OAuth2AuthorizedClient
。但是,OAuth2AuthorizedClient
的解析方式无关紧要。
@GetMapping("/explicit")
Mono<String> explicit(@RegisteredOAuth2AuthorizedClient("client-id") OAuth2AuthorizedClient authorizedClient) {
return this.webClient
.get()
.uri(this.uri)
.attributes(oauth2AuthorizedClient(authorizedClient))
.retrieve()
.bodyToMono(String.class);
}
21.4 clientRegistrationId
或者,可以在请求属性上指定clientRegistrationId
,而WebClient
将尝试查找OAuth2AuthorizedClient
。如果找不到,将自动获取一个。
Mono<String> body = this.webClient
.get()
.uri(this.uri)
.attributes(clientRegistrationId("client-id"))
.retrieve()
.bodyToMono(String.class);