spring-boot - 如何为不同的服务配置多个 OAuth2RestTemplates?

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

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

我相信我确实读过你不能有多个范围,因为每个 JWT token 都是资源特定的,但我看不到有多个 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;
    }

最佳答案

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

<dependency>
  <groupId>org.springframework.security.oauth.boot</groupId>
  <artifactId>spring-security-oauth2-autoconfigure</artifactId>
  <version>2.0.0.RELEASE</version>
</dependency>
在 configuration.yml 文件中,您必须设置客户端所需的所有属性才能从授权服务器获取 token 。
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 header 中使用相应的 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 会在 token 过期时自动刷新 token ,这太酷了。

关于spring-boot - 如何为不同的服务配置多个 OAuth2RestTemplates?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62222738/

相关文章:

spring-boot - 了解 Elixir

react-native - 给定 oauth_app 资源未找到 - Magic.Link

spring-security - 如何对受 OAuth 保护的 REST api 实现速率限制?

java - 使用SSO时如何处理Http session 超时

java - Spring Boot 不记名 token 身份验证给出 401

spring - 如何使用基本身份验证保护 spring cloud eureka 服务?

java - Spring @Transactional 只有在调用者也是@Transactional 时才有效

javascript - 无法使用客户端(隐式)身份验证登录 Instagram

google-apps-script - "Authorisation is required to perform that action"消息,即使在单击 "Allow"之后

java - Spring Boot - Spring Security - InvalidBearerTokenException 错误处理