尝试使用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:作为替代方案,我尝试了这里描述的方法:How to set HTTP Header for OAuth2RestTemplate哪个实现AccessTokenProvider
并在obtainAccessToken
中设置标题。但这也没有帮助。
当你为构造函数创建新的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,你就可以使用感兴趣的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);
}
}
如果你看到上面的图片,你可以看到你做的时间:
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);
我希望我帮助过你。
您可以使用拦截器来包装您的请求,请参阅ClientHttpRequestInterceptor#intercept
:
截距
ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException拦截给定的请求,并返回响应。给定的
ClientHttpRequestExecution
允许拦截器传递请求并响应链中的下一个实体。此方法的典型实现将遵循以下模式:
- 检查请求和正文
- (可选)包装请求以过滤HTTP属性。
- (可选)修改请求的正文。
- 或 使用
ClientHttpRequestExecution.execute(org.springframework.http.HttpRequest, byte[])
执行请求, 要么 不要执行完全阻止执行的请求。- (可选)将响应包装为过滤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
}
}