【问题标题】:How to configure multiple OAuth2RestTemplates for different services?如何为不同的服务配置多个 OAuth2RestTemplates?
【发布时间】:2020-09-25 02:19:32
【问题描述】:

如何使用 Spring Boot 配置多个 OAuth2RestTemplates(通过 OAuth2ProtectedResourceDetails),以便我可以访问多个 API。正如我们所见,它们都配置在同一个租户中,除了范围之外,所有配置都相同。

我相信我确实读过你不能有多个范围,因为每个 JWT 令牌都是特定于资源的,但我看不到有多个 RestTemplates 的示例。

谢谢!

security:
  oauth2:
    client:
      client-id: x
      client-secret: y
      user-authorization-uri: z
      access-token-uri: a
      scope: B
      grant-type: client_credentials

    client2:
      client-id: x
      client-secret: y
      user-authorization-uri: z
      access-token-uri: a
      scope: Q
      grant-type: client_credentials
    @Bean(name="ngsWbRestTemplate")
    public OAuth2RestTemplate buildNgsWbRestTemplate(
            OAuth2ProtectedResourceDetails oAuth2ProtectedResourceDetails
    ){
        OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(oAuth2ProtectedResourceDetails);
        restTemplate.setMessageConverters(Collections.singletonList(new MappingJackson2HttpMessageConverter()));
        restTemplate.getAccessToken().getValue();
        return restTemplate;
    }

    @Bean(name="OdpRestTemplate")
    public OAuth2RestTemplate buildOdpRestTemplate(
            OAuth2ProtectedResourceDetails oAuth2ProtectedResourceDetails,
            @Value("#{propertyService.getValue('ODP_BASE_URI')}") String odpBaseUri
    ){
        OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(oAuth2ProtectedResourceDetails);
        restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(odpBaseUri));
        restTemplate.setMessageConverters(Collections.singletonList(new MappingJackson2HttpMessageConverter()));
        // test access token retrieval
        restTemplate.getAccessToken().getValue();
        return restTemplate;
    }

【问题讨论】:

    标签: spring-boot oauth-2.0 spring-security-oauth2 oauth2resttemplate


    【解决方案1】:

    我最近做了一个客户端,它集成了多个使用 OAUth2 协议保护其 API 的提供商的信息。我使用了这个依赖:

    <dependency>
      <groupId>org.springframework.security.oauth.boot</groupId>
      <artifactId>spring-security-oauth2-autoconfigure</artifactId>
      <version>2.0.0.RELEASE</version>
    </dependency>
    

    在 configuration.yml 文件中,您必须设置客户端所需的所有属性才能从授权服务器获取令牌。

    example:
     oauth2:
       okta:
         clientId: XXX-XXX-XXX
         clientSecret: XXX-XXX-XXX
         grantType: client_credentials
         accessTokenUri: https://dev-xxxx.okta.com/oauth2/default/v1/token
         scope: custom_service #Created in okta
       keycloak:
         clientId: app-resource-server
         clientSecret: 60bc378c-5c95-4dee-b525-e71993d1596d
         grantType: password  #For password grant_type
         username: user
         password: user
         accessTokenUri: http://localhost:9001/auth/realms/development/protocol/openid-connect/token
         scope: openid profile email
    

    在主类中,您需要为要发送请求的每个资源服务器创建一个不同的 bean,并在 Authorization 标头中使用相应的 access_token。

    @SpringBootApplication
    public class DemoApplication {
    
    
        /* Inject your client properties into ClientCredentialsResourceDetails object
           if you need to get tokens using client_credentials grant type*/
        @Bean
        @ConfigurationProperties("example.oauth2.okta")
        protected ClientCredentialsResourceDetails oktaOAuth2Details() {
            return new ClientCredentialsResourceDetails();
        }
    
        /*Inject your client properties into ResourceOwnerPasswordResourceDetails object
          if you need to pass an username and a password*/
        @Bean
        @ConfigurationProperties("example.oauth2.keycloak")
        protected ResourceOwnerPasswordResourceDetails keycloakOAuth2Details() {
            return new ResourceOwnerPasswordResourceDetails();
        }
    
        //Create the OAuth2RestTemplate bean with the corresponding clientOAuth2Details
        @Bean("oktaOAuth2RestTemplate")
        protected OAuth2RestTemplate oktaOAuth2RestTemplate() {
            return new OAuth2RestTemplate(oktaOAuth2Details());
        }
    
        @Bean("keycloakOAuth2RestTemplate")
        protected OAuth2RestTemplate keycloakOAuth2RestTemplate() {
            return new OAuth2RestTemplate(keycloakOAuth2Details());
        }
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
    }
    

    然后您可以使用@Qualifier 注解选择所需的实现来自动装配 OAuth2RestTemplate,如下所示

    @Component
    public class AsyncService {
    
        //@Value("#{ @environment['example.baseUrl'] }")
        private static final String API_URL1 = "http://localhost:8081";
        private static final String API_URL2 = "http://localhost:8082";
    
        private final Logger log = LoggerFactory.getLogger(AsyncService.class);
    
        @Autowired
        @Qualifier("oktaOAuth2RestTemplate")
        OAuth2RestTemplate oktaOAuth2RestTemplate;
    
        @Autowired
        @Qualifier("keycloakOAuth2RestTemplate")
        OAuth2RestTemplate keycloakOAuth2RestTemplate;
    
        public void oktaRequest() {
            log.info("Okta access_token: {}", oktaOAuth2RestTemplate.getAccessToken());
            log.info(oktaOAuth2RestTemplate.getForObject(API_URL1 + "/message", String.class));
        }
    
        public void keylcloakRequest() {
            log.info("Keycloak access_token: {}", keycloakOAuth2RestTemplate.getAccessToken());
            log.info(keycloakOAuth2RestTemplate.getForObject(API_URL2 + "/message", String.class));
        }
    
        //@Async
        public void requestMessage() {
            oktaRequest();
            keycloakRequest();
        }
    }
    

    Spring 会在令牌过期时自动刷新令牌,这太酷了。

    【讨论】:

      猜你喜欢
      • 2018-12-15
      • 1970-01-01
      • 2018-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-13
      • 1970-01-01
      相关资源
      最近更新 更多