Обновление OAuth-токена в Spring при загрузке OAuth2RestOperations - PullRequest
0 голосов
/ 21 октября 2019

Я использую OAuth-клиент Spring Boot Cloud для подключения к Salesforce restapi. Однако я получаю Session expired or invalid ошибку. Есть ли способ обновить токен? Я предполагал, что Spring Boot автоматически обрабатывает это под капотом, но, похоже, это не так. Вот соответствующий код.

@Configuration
public class SalesforceConfiguration {

    @Value("${salesforce.tokenUrl}")
    private String tokenUrl;

    @Value("${salesforce.clientId}")
    private String clientId;

    @Value("${salesforce.clientSecret}")
    private String clientSecret;

    @Value("${salesforce.username}")
    private String username;

    @Value("${salesforce.password}")
    private String password;

    @Bean
    protected OAuth2ProtectedResourceDetails resource() {

        ResourceOwnerPasswordResourceDetails resource = new ResourceOwnerPasswordResourceDetails();

        resource.setAccessTokenUri(tokenUrl);
        resource.setClientId(clientId);
        resource.setClientSecret(clientSecret);
        resource.setClientAuthenticationScheme(AuthenticationScheme.form);
        resource.setUsername(username);
        resource.setPassword(password);

        return resource;
    }

    @Bean
    public OAuth2RestOperations restTemplate() {

        OAuth2RestTemplate operations = new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(new DefaultAccessTokenRequest()));
        operations.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
        operations.getMessageConverters().add(new StringHttpMessageConverter());

        return operations;
    }
}

, и вот как я использую его в сервисе.

@Component
public class QueryExecutor extends AbstractExecutor implements SalesforceExecutor {

    private OAuth2RestOperations restOperations;

    public QueryExecutor(OAuth2RestOperations restOperations) {

        this.restOperations = restOperations;
    }

    @Override
    public Response process(Request request) throws Exception {

        JsonNode jsonNode = restOperations.getForObject(buildUrl(request), JsonNode.class);

        return new Response<>(ResponseCode.SUCCESS_GET.getCode(), jsonNode, request.getResponseHandler());
    }

    private String buildUrl(Request request) {

        return new StringBuilder().append(getServiceUrl(restOperations))
                                  .append("/services/data/v41.0/query/?q=")
                                  .append(request.getPayload().get("query"))
                                  .toString();
    }
}

Есть ли способ без проблем обновить токен, используя этот подход, если у меня закончился сеансошибка?

Ответы [ 2 ]

1 голос
/ 21 октября 2019

Используя Spring Boot, вам не нужен весь класс конфигурации SalesforceConfiguration.

Вы можете использовать следующие зависимости:

<dependency>
    <groupId>org.springframework.security.oauth.boot</groupId>
    <artifactId>spring-security-oauth2-autoconfigure</artifactId>
     <version>${look-for-the-latest}</version>
</dependency>

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-client</artifactId>
</dependency>

Добавить свойства конфигурации в application.yml:

security:
  oauth2:
    client:
      username: the-username
      password: the-password
      client-id: the-client-id
      client-secret: the-client-secret
      grant-type: password,refresh_token
      scope: read
      access-token-uri: http://sales-force-domain/oauth/token

И тогда вы можете определить свой OAuth2RestTemplate следующим образом:

    @Bean
    public OAuth2RestTemplate oAuth2RestTemplate(final OAuth2ProtectedResourceDetails details) {
        return new OAuth2RestTemplate(details);
    }

Чтобы использовать его, просто делайте то, что вы уже делаете, введите OAuth2RestTemplate вQueryExecutor. Токен обновления будет обработан Spring, как только вы определили его как grant-type в application.yml.

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

0 голосов
/ 01 ноября 2019

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

@Component
public class QueryExecutor implements SalesforceExecutor {

    private OAuth2RestOperations restOperations;

    public QueryExecutor(OAuth2RestOperations restOperations) {

        this.restOperations = restOperations;
    }

    @Override
    public Response process(Request request) throws Exception {

        try {

            JsonNode jsonNode = restOperations.getForObject(buildUrl(request), JsonNode.class);

            return new Response<>(ResponseCode.SUCCESS_GET.getCode(), jsonNode, request.getResponseHandler());

        } catch (HttpClientErrorException | HttpServerErrorException e) {

            if (HttpStatus.UNAUTHORIZED.value() == e.getStatusCode().value()) {

                restOperations.getOAuth2ClientContext().setAccessToken(this.getRenewedToken(restOperations.getResource()));
            }

            // retry again with renewed token
        }
    }

    private String buildUrl(Request request) {

        return "someurl";
    }

    private OAuth2AccessToken getRenewedToken(OAuth2ProtectedResourceDetails resource) {

        OAuth2RestTemplate oAuth2RestTemplate = new OAuth2RestTemplate(resource, new DefaultOAuth2ClientContext(new DefaultAccessTokenRequest()));

        return oAuth2RestTemplate.getOAuth2ClientContext().getAccessToken();
    }
}

Вот так.

...