OAuth2RestTemplate добавляет кодировку в заголовок типа контента - PullRequest
3 голосов
/ 06 апреля 2019

При попытке получить токен доступа с помощью OAuth2RequestTemplate, вызов отправляет указанный ниже заголовок в запросе

"Content-Type", "application/x-www-form-urlencoded;charset=UTF-8”

Я бы хотел уронить кодировку, чтобы ее там не было.

Я пытался установить значение заголовка вручную через объект AccessTokenRequest и CustomTokenProvider, но это не сработало.

Любая идея, почему это на самом деле включает его и как от него избавиться.

ОБНОВЛЕНИЕ: включая пример кода

ВАРИАНТ 1:

String oauthServerUri = "..../access_token";

ClientCredentialsResourceDetails ccDetails = new ClientCredentialsResourceDetails();
ccDetails.setClientId("clientId");
ccDetails.setClientSecret("clientSecret");
ccDetails.setGrantType("client_credentials");
ccDetails.setAccessTokenUri(oauthServerUri);

AccessTokenRequest tokenRequest = new DefaultAccessTokenRequest();

Map<String, List<String>> headers = new HashMap<>();
headers.put("Content-Type", Arrays.asList("Some Proper Value"));
tokenRequest.setHeaders(headers);
OAuth2ClientContext context = new DefaultOAuth2ClientContext(tokenRequest);

OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(ccDetails, context);
OAuth2AccessToken accessToken = restTemplate.getAccessToken();

ВАРИАНТ 2: В качестве альтернативы я попробовал подход, описанный здесь: Как установить заголовок HTTP для OAuth2RestTemplate Который реализует AccessTokenProvider и устанавливает заголовки в obtainAccessToken. Но и это не помогло.

Ответы [ 2 ]

0 голосов
/ 13 апреля 2019

Вы можете использовать перехватчик для упаковки запроса, см. ClientHttpRequestInterceptor#intercept:

перехват

ClientHttpResponse intercept(HttpRequest request,
                             byte[] body,
                             ClientHttpRequestExecution execution)
                      throws IOException 

Перехватна данный запрос и вернуть ответ.Данный ClientHttpRequestExecution позволяет перехватчику передавать запрос и ответ следующему объекту в цепочке.

Типичная реализация этого метода будет следовать следующей схеме:

  1. Изучите запрос и тело
  2. При желании оберните запрос для фильтрации атрибутов HTTP.
  3. При желании измените тело запроса.
  4. Либо
    выполните запрос, используя ClientHttpRequestExecution.execute(org.springframework.http.HttpRequest, byte[]),
    или
    не выполняют запрос, чтобы полностью заблокировать выполнение.
  5. При желании упаковывают ответ для фильтрации атрибутов HTTP.

Ваш модифицированный код:

OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(ccDetails, context);
restTemplate.setInterceptors(Arrays.asList(new new RestTemplateHeaderModifierInterceptor()));
OAuth2AccessToken accessToken = restTemplate.getAccessToken();

с

public class RestTemplateHeaderModifierInterceptor implements ClientHttpRequestInterceptor {

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        HttpRequest requestWrapper = new CustomHttpRequestWrapper(request);
        return execution.execute(requestWrapper, body);
    }
}

public class CustomHttpRequestWrapper extends HttpRequestWrapper {

    public CustomHttpRequestWrapper(HttpRequest request) {
        super(request)
    }        

    @Override
    public HttpHeaders getHeaders() {
        // return all headers, but change the charset
    }
}
0 голосов
/ 09 апреля 2019

Когда вы делаете конструктор новым OAuth2RestTemplate (ccDetails, context);позади него создается super (), который создает RestTemplate, потому что он расширяет его.

public OAuth2RestTemplate(OAuth2ProtectedResourceDetails resource, OAuth2ClientContext context) {
        super();
        if (resource == null) {
            throw new IllegalArgumentException("An OAuth2 resource must be supplied.");
        }

        this.resource = resource;
        this.context = context;
        setErrorHandler(new OAuth2ErrorHandler(resource));
    }

Конструктор RestTemplate помещает messageConverters по умолчанию.

public RestTemplate() {
        this.messageConverters.add(new ByteArrayHttpMessageConverter());
        this.messageConverters.add(new StringHttpMessageConverter());
......

Возможно, решение может быть когда-тоСоздав объект OAuth2RestTemplate, вы создаете restTemplate.setMessageConverters (messageConverters) с MediaType, который вас интересует, из этого метода (внутри класса RestTemplate) удаляет предыдущие:

public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
        Assert.notEmpty(messageConverters, "At least one HttpMessageConverter required");
        // Take getMessageConverters() List as-is when passed in here
        if (this.messageConverters != messageConverters) {
            this.messageConverters.clear();
            this.messageConverters.addAll(messageConverters);
        }
    }

РЕДАКТИРОВАТЬ: Members calling

Если вы видите изображение выше, вы можете увидеть, когда вы делаете:

restTemplate.getAccessToken();

вызов

getRequestCallback(resource, form, headers), extractor, form.toSingleValueMap());

protected RequestCallback getRequestCallback(OAuth2ProtectedResourceDetails resource,
        MultiValueMap<String, String> form, HttpHeaders headers) {
    return new OAuth2AuthTokenCallback(form, headers);
}

ипосмотрите, что делает его конструктор:

/**
     * Request callback implementation that writes the given object to the request stream.
     */
    private class OAuth2AuthTokenCallback implements RequestCallback {

        private final MultiValueMap<String, String> form;

        private final HttpHeaders headers;

        private OAuth2AuthTokenCallback(MultiValueMap<String, String> form, HttpHeaders headers) {
            this.form = form;
            this.headers = headers;
        }

        public void doWithRequest(ClientHttpRequest request) throws IOException {
            request.getHeaders().putAll(this.headers);
            request.getHeaders().setAccept(
                    Arrays.asList(MediaType.APPLICATION_JSON, MediaType.APPLICATION_FORM_URLENCODED));
            FORM_MESSAGE_CONVERTER.write(this.form, MediaType.APPLICATION_FORM_URLENCODED, request);
        }
    }

Может быть, с помощью методов наследования и перезаписи вы можете передать этому построителю интересующие вас заголовки.

Также в OAuth2AccessTokenSupport у метода retrieveToken есть интересные комментарии.:

// Prepare headers and form before going into rest template call in case the URI is affected by the result
authenticationHandler.authenticateTokenRequest(resource, form, headers);
// Opportunity to customize form and headers
tokenRequestEnhancer.enhance(request, resource, form, headers);

Надеюсь, я тебе помог.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...