java - 如何处理 OAuth 网络客户端异常
问题描述
我对 Spring 很陌生,并且在通过 OAUTH 对服务器进行身份验证时一直试图捕获未经授权的异常。我不明白为什么方法 handleResponseError() 没有捕捉到异常。
我得到的堆栈跟踪是:
org.springframework.security.oauth2.client.ClientAuthorizationException: [invalid_client] Client authentication failed
at org.springframework.security.oauth2.client.ClientCredentialsReactiveOAuth2AuthorizedClientProvider.lambda$authorize$0(ClientCredentialsReactiveOAuth2AuthorizedClientProvider.java:82)
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ Request to GET https://localhost:8181/catalog/NL/brands?language_code=nl [DefaultWebClient]
Stack trace:
at org.springframework.security.oauth2.client.ClientCredentialsReactiveOAuth2AuthorizedClientProvider.lambda$authorize$0(ClientCredentialsReactiveOAuth2AuthorizedClientProvider.java:82)
at reactor.core.publisher.Mono.lambda$onErrorMap$29(Mono.java:3272)
at reactor.core.publisher.Mono.lambda$onErrorResume$31(Mono.java:3362)
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:88)
at reactor.core.publisher.FluxHide$SuppressFuseableSubscriber.onError(FluxHide.java:132)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.secondError(MonoFlatMap.java:185)
at reactor.core.publisher.MonoFlatMap$FlatMapInner.onError(MonoFlatMap.java:251)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onError(FluxMapFuseable.java:134)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onError(FluxMapFuseable.java:134)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:135)
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:114)
at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:67)
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:73)
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1782)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:144)
向服务器进行身份验证的代码:
@Bean
public WebClient myClient() {
InMemoryReactiveClientRegistrationRepository clientRegistryRepo = new InMemoryReactiveClientRegistrationRepository(getClientRegistration());
InMemoryReactiveOAuth2AuthorizedClientService clientService = new InMemoryReactiveOAuth2AuthorizedClientService(clientRegistryRepo);
AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager = new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(clientRegistryRepo, clientService);
ServerOAuth2AuthorizedClientExchangeFilterFunction oauthFilter = new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
oauthFilter.setDefaultClientRegistrationId(OAUTH_PROVIDER_NAME);
return WebClient.builder()
.clientConnector(new JettyClientHttpConnector(createHttpClient()))
.exchangeStrategies(getMaxMessageInMemorySize(maxInMemorySize))
.baseUrl(baseURL)
.filter(oauthFilter)
.filter(handleResponseError())
.build();
}
private static ExchangeFilterFunction handleResponseError() {
return ExchangeFilterFunction.ofResponseProcessor(
response -> response.statusCode().isError() ?
response.bodyToMono(String.class)
.flatMap(errorBody -> Mono.error(new MyUnAuthorizedRequestException(response.statusCode().name(), errorBody, ""))) :
Mono.just(response));
}
我看过各种例子:
我使用@ControllerAdvice 捕获所有其他异常。这是处理这个问题的正确方法吗?
解决方案
我找到了解决方案:
.... omitted
ServerOAuth2AuthorizedClientExchangeFilterFunction oauthFilter = new
ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
oauthFilter.setDefaultClientRegistrationId(OAUTH_PROVIDER_NAME);
return WebClient.builder()
.clientConnector(new JettyClientHttpConnector(createHttpClient()))
.exchangeStrategies(getMaxMessageInMemorySize(maxInMemorySize))
.baseUrl(baseURL)
.filter(oauthFilter)
.build();
}
private ReactiveOAuth2AuthorizationFailureHandler getReactiveOAuth2AuthorizationFailureHandler() {
final ReactiveOAuth2AuthorizationFailureHandler reactiveOAuth2AuthorizationFailureHandler = (authorizationException, principal, attributes) -> {
if (authorizationException instanceof ClientAuthorizationException) {
ClientAuthorizationException clientAuthorizationException = (ClientAuthorizationException)authorizationException;
return Mono.error(new MyUnAuthorizedRequestException("401","Could not authorize client", clientAuthorizationException.getMessage()));
} else {
return Mono.empty();
}
};
return reactiveOAuth2AuthorizationFailureHandler;
}
推荐阅读
- python - 从 selenium 访问时网站略微更改其 UI - Chromedriver
- java - 如何创建一个“软”断开的 TCP 连接,就好像网络硬件已经默默地断开了流?
- python - python 类中的方法可以用子类定义的类型进行注释吗?
- ruby - 红宝石。打乱数组,使相邻的元素没有相同的值
- css - 造型道具不起作用,尤其是填充
- java - 如何解决我在 Java 中遇到的异常日志记录问题?
- linkedin - 在 API 调用中返回 {"id":"private"} 的公共配置文件
- android - 从 CameraX analyze() 导航到另一个片段会阻止当前片段的生命周期并冻结 UI
- php - JS(Jquery) 和 PHP Etag 在 Apache 上不起作用
- vba - 为什么每次单击 VBA 用户窗体进度条都会更新?