OAuth2RestTemplate 将字符集添加到内容类型标头中

NDe*_*per 5 java spring oauth spring-security spring-boot

当尝试使用 OAuth2RequestTemplate 获取访问令牌时,调用会在请求中发送以下标头

\n\n
"Content-Type", "application/x-www-form-urlencoded;charset=UTF-8\xe2\x80\x9d\n
Run Code Online (Sandbox Code Playgroud)\n\n

I\xe2\x80\x99d 喜欢删除字符集,使其不包含在那里。

\n\n

我尝试通过 AccessTokenRequest 对象和 CustomTokenProvider 手动设置标头值,但它不起作用。

\n\n

知道为什么它实际上包含它以及如何摆脱它。

\n\n

更新:包括代码示例

\n\n

选项1 :

\n\n
String oauthServerUri = "..../access_token";\n\nClientCredentialsResourceDetails ccDetails = new ClientCredentialsResourceDetails();\nccDetails.setClientId("clientId");\nccDetails.setClientSecret("clientSecret");\nccDetails.setGrantType("client_credentials");\nccDetails.setAccessTokenUri(oauthServerUri);\n\nAccessTokenRequest tokenRequest = new DefaultAccessTokenRequest();\n\nMap<String, List<String>> headers = new HashMap<>();\nheaders.put("Content-Type", Arrays.asList("Some Proper Value"));\ntokenRequest.setHeaders(headers);\nOAuth2ClientContext context = new DefaultOAuth2ClientContext(tokenRequest);\n\nOAuth2RestTemplate restTemplate = new OAuth2RestTemplate(ccDetails, context);\nOAuth2AccessToken accessToken = restTemplate.getAccessToken();\n
Run Code Online (Sandbox Code Playgroud)\n\n

选项 2: \n作为替代方案,我尝试了此处描述的方法:\n如何为 OAuth2RestTemplate 设置 HTTP 标头\n这是AccessTokenProviderobtainAccessToken. 但这也没有帮助。

\n

Fra*_*cio 0

当您创建构造函数 new 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));
    }
Run Code Online (Sandbox Code Playgroud)

RestTemplate 构造函数默认放置 messageConverters。

public RestTemplate() {
        this.messageConverters.add(new ByteArrayHttpMessageConverter());
        this.messageConverters.add(new StringHttpMessageConverter());
......
Run Code Online (Sandbox Code Playgroud)

也许解决方案可能是,一旦创建了对象 OAuth2RestTemplate,您就可以使用您感兴趣的 MediaType 创建一个restTemplate.setMessageConverters(messageConverters),从此方法(在 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);
        }
    }
Run Code Online (Sandbox Code Playgroud)

编辑: 会员来电

如果您看到上图,您就可以看到:

restTemplate.getAccessToken();
Run Code Online (Sandbox Code Playgroud)

拨电至

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

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

看看他的构造函数做了什么:

/**
     * 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);
        }
    }
Run Code Online (Sandbox Code Playgroud)

也许通过继承和覆盖方法,您可以将您感兴趣的标头传递给该构建器。

另外,在 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);
Run Code Online (Sandbox Code Playgroud)

我希望我对你有帮助。