Несколько дней назад была поставлена задача сделать запросы между сервисами с токеном. У нас используется Keycloak в качестве SSO. В силу того, что нужно всё на базовом уровне (ничего специфического),то имеет смысл использовать Feign Client (OpenFeign) для Spring Boot.
Начал копаться в вопросе включения OAuth для Feign и через 1-2 дня наткнулся на только что опубликованную статью от @Kinski, но, как и везде, в ней и в других статьях есть некоторые неточности и даже в той же документации. Опишу различные варианты включения, которые я счёл верными и простыми с некоторым описанием.
В нашем случае client.registration у нас keycloak.
Spring Boot 2.7.6
Spring Cloud 2021.0.5
1. Включаем OAuth2 для всех Feign клиентов
Первая неточность по документации — это параметры включения как раз этого OAuth для Feign. Вместо настроек для Spring
spring: cloud: openfeign: oauth2: enabled: true clientRegistrationId: keycloak
которые ничего не включат.
-
надо использовать
feign: oauth2: enabled: true clientRegistrationId: keycloak
естественно подключаем пакеты:
— spring-boot-starter-security
— spring-boot-starter-oauth2-client
— spring-cloud-starter-openfeign.
-
Далее включаем сам OAuth2Client security
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http // ваши настройки + .oauth2Client(); return http.build(); }
-
ну и прописываем настройки для OAuth2 клиента
spring: security: oauth2: client: registration: keycloak: client-id: id вашего клиента для провайдера client-secret: ваш секрет authorization-grant-type: client_credentials provider: keycloak provider: keycloak: token-uri: адрес до провайдера токена
После этого все запросы через Feign Client будут обогощаться OAuth токеном.
2. Включаем OAuth2 только для нужных Feign клиентов
Повторяем из 1го раздела пункты 3 и 4. Далее создаём конфигурацию для Feign
public class OAuthFeignConfig { private final OAuth2ClientProperties oAuth2ClientProperties; public OAuthFeignConfig(OAuth2ClientProperties oAuth2ClientProperties) { this.oAuth2ClientProperties = oAuth2ClientProperties; } @Bean @ConditionalOnBean({OAuth2AuthorizedClientService.class, ClientRegistrationRepository.class}) @ConditionalOnMissingBean public OAuth2AuthorizedClientManager feignOAuth2AuthorizedClientManager(ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientService oAuth2AuthorizedClientService) { return new AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, oAuth2AuthorizedClientService); } @Bean @ConditionalOnBean(OAuth2AuthorizedClientManager.class) public OAuth2AccessTokenInterceptor defaultOAuth2AccessTokenInterceptor(OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager) { return new OAuth2AccessTokenInterceptor(oAuth2ClientProperties.getRegistration().keySet().iterator().next(), oAuth2AuthorizedClientManager); } }
Фактически код создания бинов скопирован из исходников и поправлен только в моменте прописывания имени клиентской регистрации из настроек.
В раскопках помогли исходники:
-
FeignAutoConfigurationfromorg.springframework.cloud.openfeign -
OAuth2AccessTokenInterceptorfromorg.springframework.cloud.openfeign.security
В 19й строке использовал oAuth2ClientProperties.getRegistration().keySet().iterator().next() для получения первой в списке регистрации (чтобы не хардкодить. У нас это keycloak).
теперь в любом нашем FeignClient дописываем конфигурацию:
@FeignClient(value = "client-name", url = "your_url", configuration = OAuthFeignConfig.class)
PS: статья первая,сильно не бейте. Решил оформить после статьи от @Kinskiс более детальным описанием и раскрытием нюансов, которые на просторах интернета не описаны нигде.
Если кому-то статья сократит время разработки и поможет — буду рад!
ссылка на оригинал статьи https://habr.com/ru/post/719934/
Добавить комментарий