Как Spring Security 5.2 / WebClient использует имя пользователя и пароль для подключения к другой службе? - PullRequest
0 голосов
/ 14 января 2020

В настоящее время у нас есть несколько приложений Spring Boot, подключающихся к другим сервисам с использованием учетной записи службы. До сих пор мы использовали AccessTokenRequest OAuth2ClientContext на RestTemplate, чтобы поместить пользователя и пароль учетной записи службы, и использовали возвращенный токен OAuth для подключения к другим службам.

Сейчас мы создаем новый Для приложения, использующего Spring Boot 5.2, и поскольку теперь необходимо использовать новый OAuth Spring Security, отдельная библиотека OAuth устарела, мы также хотели бы заменить решение RestTemplate на решение WebClient, так как RestTemplate также станет устаревшим в ближайшем будущем. Я пробовал несколько способов получения токена, но не смог найти решение, которое работает.

Я нашел настройки, подобные упомянутым в Spring Security 5 Replacement for OAuth2RestTemplate , но нет способа поместить имя пользователя и пароль в WebClient. Я обнаружил другие подходы, использующие ClientRegistrationRepository вместо ReactiveClientRegistrationRepository, и некоторые из этих подходов на самом деле имеют варианты (например, Как повторно инициализировать предоставление пароля в Spring security 5.2 OAuth ) для помещения имени пользователя и пароля в AuthorizedClientManager, который становится параметром при создании экземпляра фильтра, но каким-то образом я всегда получаю сообщение о том, что невозможно найти Bean-компонент ClientRegistrationRepository, независимо от того, какие свойства я добавляю в application.yaml (возможно, это не работает, потому что приложение такое приложение MVC вместо WebFlux?)

Я знаю, что мне нужно установить тип разрешения авторизации как «пароль», но уже есть кто-то, кто спрашивает, как заставить это работать ( Spring Security 5.2.1 + spring-security-oauth2 + WebClient: как использовать тип предоставления пароля ) и пока нет ответов на этот вопрос.

Так что ... они сделали? не одобряйте этот простой способ использования usern ame и пароль, чтобы получить токен и использовать этот токен для подключения к другому сервису в Spring Security 5.2? И если да, что следует использовать сейчас?

Ответы [ 2 ]

1 голос
/ 14 января 2020

Да, RestTemplate и OAuthRestTemplate устарели. WebClient поддерживает OAuth из коробки. Вам не нужно делать ничего особенного или добавлять заголовки самостоятельно. Это на самом деле очень тривиально.

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

@Bean
public WebClient webClient(ReactiveClientRegistrationRepository clientRegistrations) {
        return WebClient.builder().filter(filterFunction(clientRegistrations))
                                  .baseUrl(String.format("http://%s:8080", getHostName()))
                                  .build();

}

    private ServerOAuth2AuthorizedClientExchangeFilterFunction filterFunction(ReactiveClientRegistrationRepository clientRegistrations) {
        ServerOAuth2AuthorizedClientExchangeFilterFunction filterFunction = new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, new UnAuthenticatedServerOAuth2AuthorizedClientRepository());
        filterFunction.setDefaultClientRegistrationId("myKey");
        return filterFunction;
    }

ПРИМЕЧАНИЕ. В функции фильтра замените «myKey» на нечто, соответствующее следующей структуре свойств в application.properties (замените myKey в пути собственности с вашим именем):

spring.security.oauth2.client.registration.myKey.authorization-grant-type=password
spring.security.oauth2.client.registration.myKey.client-id=xxx
spring.security.oauth2.client.registration.myKey.client-secret=xxx

spring.security.oauth2.client.provider.myKey.token-uri=http://localhost:8080/oauth/token

Aaaann ddd .... все готово! OAuth токен refre sh также встроен.

0 голосов
/ 16 января 2020

Ну, это оказалось немного по-другому. Комментарий к последнему SO-связанному вопросу, который я связал, попросил автора использовать отладку в PasswordOAuth2AuthorizedClientProvider, чтобы увидеть, что произошло / не так. Итак, я также начал отладку, и с предоставленной вами настройкой есть 4 провайдера для 4 типов входа, которые поставляются, но из 4 это не PasswordReactiveOAuth2AuthorizedProvider, который используется, а также не ClientCredentialsReactiveOAuth2AuthorizedProvider или RefreshTokenReactiveOAuth2AuthorizedProviderCore_Authorized, один из которых является и это довольно странно, когда тип разрешения авторизации установлен на пароль. Мне это кажется ошибкой ...

В любом случае, я нашел еще один SO-вопрос от Rigon, в котором проблема немного отличается от моей, но достаточно близкая: Создание маршрута в Spring Cloud Gateway с ресурсом OAuth2 Тип предоставления пароля владельца и он предоставил код, который я мог бы использовать, поскольку поставщик, используемый с этой кодовой базой, на самом деле является PasswordReactiveOAuth2AuthorizedClientProvider

В итоге мне нужно было ввести только 3 элемента в yaml-файле: client-id (с client_id, который раньше использовался как атрибут в AccessTokenRequest), тип авторизации-предоставления и token-uri. Кроме того, я скопировал настройки WebClient и ReactiveOAuth2AuthorizedClientManager из кода, предоставленного rigon, и поместил имя пользователя и пароль из файла конфигурации в настройки (я оставил отдельный contextAttributesMapper, так как мне нужно было только предоставить 2 параметра контекста непосредственно в карту).

...