Как использовать Spring WebClient для неинтерактивного доступа к защищенному OAuth-ресурсу от имени другого пользователя? - PullRequest
3 голосов
/ 25 марта 2019

У меня есть приложение Spring (не Boot), которое должно неинтерактивно (в запланированном задании) получать доступ к некоторым сторонним ресурсам от имени наших пользователей. Эти ресурсы используют OAuth 2.0 для авторизации. У нас уже есть рабочий процесс, который получает нам необходимые токены и получает доступ к ресурсам, используя Spring Social или нашу собственную реализацию, ни одна из которых не является оптимальной (Spring Social, кажется, не поддерживается, мы бы предпочли использовать библиотеку, чем поддерживать OAuth » рамки ").

Я пытаюсь использовать WebClient из Spring Security 5.1, но я не уверен, что я использую его правильно.

WebClient создается следующим образом:

final ClientRegistration 3rdParty = 3rdParty();

final ReactiveClientRegistrationRepository clientRegistrationRepository =
    new InMemoryReactiveClientRegistrationRepository(3rdParty);

final ReactiveOAuth2AuthorizedClientService authorizedClientService =
    new InMemoryReactiveOAuth2AuthorizedClientService(clientRegistrationRepository);

final ServerOAuth2AuthorizedClientRepository authorizedClientRepository =
    new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository(authorizedClientService);

final ServerOAuth2AuthorizedClientExchangeFilterFunction autorizedClientExchangeFilterFunction =
    new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrationRepository, authorizedClientRepository);

return WebClient.builder()
    .filter(autorizedClientExchangeFilterFunction)
    .build();

и доступ к ресурсу таким образом работает:

final OAuth2AuthorizedClient oAuth2AuthorizedClient = ... // (OAuth2AuthorizedClient with OAuth2AccessToken)

final Mono<SomeResource> someResourceMono = webClient().get()
    .uri(3rdpartyUrl)
    .attributes(ServerOAuth2AuthorizedClientExchangeFilterFunction.oauth2AuthorizedClient(oAuth2AuthorizedClient))
    .retrieve()
    .bodyToMono(SomeResource.class);

Проблема в том, что я не понимаю, как ReactiveClientRegistrationRepository и ServerOAuth2AuthorizedClientRepository используются в этом подходе. Если мне нужно создать полностью заполненный OAuth2AuthorizedClient для доступа к ресурсу, зачем нужны эти репозитории?

Я ожидал, что мне нужно передать clientRegistrationId, некоторый "PrincipalName", реализовать наши ReactiveOAuth2AuthorizedClientService загрузки OAuth2AuthorizedClient с помощью "PrincipalName" и позволить ServerOAuth2AuthorizedClientRepository делать свою работу, но я вижу только так Для передачи принципала в WebClient используется ServerOAuth2AuthorizedClientExchangeFilterFunction#oauth2AuthorizedClient, для которого требуется полный OAuth2AuthorizedClient. Какую часть я делаю неправильно?

1 Ответ

0 голосов
/ 08 апреля 2019

Вместо предоставления OAuth2AuthorizedClient через oauth2AuthorizedClient(), вы также можете предоставить clientRegistrationId через clientRegistrationId() и ServerWebExchange через serverWebExchange(). Комбинация двух последних опций разрешит Principal из ServerWebExchange и использует оба значения ReactiveClientRegistrationRepository и ServerOAuth2AuthorizedClientRepository для разрешения OAuth2AuthorizedClient. Я понимаю, что ваш вариант использования немного отличается, учитывая, что вы работаете вне контекста запроса - это просто К вашему сведению.

... Проблема в том, что я не понимаю, как ReactiveClientRegistrationRepository и ServerOAuth2AuthorizedClientRepository используется в этом подходе

Вам по-прежнему необходимо предоставить ReactiveClientRegistrationRepository и ServerOAuth2AuthorizedClientRepository, поскольку ServerOAuth2AuthorizedClientExchangeFilterFunction поддерживает обновление (authorization_code клиент) и обновление (client_credentials клиент) токена доступа с истекшим сроком действия.

Для вашего конкретного случая использования взгляните на UnAuthenticatedServerOAuth2AuthorizedClientRepository, так как эта реализация поддерживает WebClient, работающую вне контекста запроса, например, фоновый поток. Вот образец для справки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...