RestTemplate 未传递 Origin header
RestTemplate not passing Origin header
我正在尝试使用 Spring 的 RestTemplate 发出 cross-origin 请求。通信是在两个 Spring-boot webapps 之间完成的,它们都在本地主机上 运行 但端口不同。我做的是:
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setOrigin("http://localhost:8083");
httpHeaders.add("Authorization", token);
HttpEntity<Void> httpEntity = new HttpEntity<>(httpHeaders);
ParameterizedTypeReference<List<MyObj>> beanType = new ParameterizedTypeReference<List<MyObj>>() {};
ResponseEntity<List<MyObj>> list = restTemplate.exchange(serviceURL, HttpMethod.GET, httpEntity, beanType);
调用被执行,"Authorization" header 传递就好了,但是无论我怎么尝试,接收方都没有"Origin" header .
当我使用其他工具(SoapUI、RestClient Chrome 插件等)创建类似的请求时,header 就像我提供的那样被传递。
为了在接收方打印所有 headers,我使用了 javax.servlet.Filter 的实现:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
log.info(headerName + ": " + request.getHeader(headerName));
}
}
为什么使用RestTemplate时原点header没有通过?
遇到了我花了一个世纪才解决的同样问题。
根本原因是 RestTemplate 文档中的这一行
Note: by default the RestTemplate relies on standard JDK facilities to establish HTTP connections.
如果你查看Java中HttpUrlConnection
class的源代码,你会发现下面的代码块,headerOrigin
是一个禁止更改的受限 header 的数量:
/*
* Restrict setting of request headers through the public api
* consistent with JavaScript XMLHttpRequest2 with a few
* exceptions. Disallowed headers are silently ignored for
* backwards compatibility reasons rather than throwing a
* SecurityException. For example, some applets set the
* Host header since old JREs did not implement HTTP 1.1.
* Additionally, any header starting with Sec- is
* disallowed.
*
* The following headers are allowed for historical reasons:
*
* Accept-Charset, Accept-Encoding, Cookie, Cookie2, Date,
* Referer, TE, User-Agent, headers beginning with Proxy-.
*
* The following headers are allowed in a limited form:
*
* Connection: close
*
* See http://www.w3.org/TR/XMLHttpRequest2.
*/
private static final boolean allowRestrictedHeaders;
private static final Set<String> restrictedHeaderSet;
private static final String[] restrictedHeaders = {
/* Restricted by XMLHttpRequest2 */
//"Accept-Charset",
//"Accept-Encoding",
"Access-Control-Request-Headers",
"Access-Control-Request-Method",
"Connection", /* close is allowed */
"Content-Length",
//"Cookie",
//"Cookie2",
"Content-Transfer-Encoding",
//"Date",
//"Expect",
"Host",
"Keep-Alive",
"Origin",
// "Referer",
// "TE",
"Trailer",
"Transfer-Encoding",
"Upgrade",
//"User-Agent",
"Via"
};
这个问题有一个简单的修复方法,只需设置一个 JVM 参数
-Dsun.net.http.allowRestrictedHeaders=true
或在您的代码中添加一行
System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
取消限制。
有同样的问题。我发现 apache http 客户端没有这个问题并发送请求 'Origin': http://hc.apache.org/
HttpOptions httpOptions = new
HttpOptions(url)
httpOptions.setHeader("Origin", "test")
httpOptions.setHeader("Content-Type", "application/json")
BasicHttpClientConnectionManager manager = new
BasicHttpClientConnectionManager()
HttpClient client = new MinimalHttpClient(manager)
client.execute(httpOptions)
我正在尝试使用 Spring 的 RestTemplate 发出 cross-origin 请求。通信是在两个 Spring-boot webapps 之间完成的,它们都在本地主机上 运行 但端口不同。我做的是:
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setOrigin("http://localhost:8083");
httpHeaders.add("Authorization", token);
HttpEntity<Void> httpEntity = new HttpEntity<>(httpHeaders);
ParameterizedTypeReference<List<MyObj>> beanType = new ParameterizedTypeReference<List<MyObj>>() {};
ResponseEntity<List<MyObj>> list = restTemplate.exchange(serviceURL, HttpMethod.GET, httpEntity, beanType);
调用被执行,"Authorization" header 传递就好了,但是无论我怎么尝试,接收方都没有"Origin" header . 当我使用其他工具(SoapUI、RestClient Chrome 插件等)创建类似的请求时,header 就像我提供的那样被传递。
为了在接收方打印所有 headers,我使用了 javax.servlet.Filter 的实现:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
log.info(headerName + ": " + request.getHeader(headerName));
}
}
为什么使用RestTemplate时原点header没有通过?
遇到了我花了一个世纪才解决的同样问题。
根本原因是 RestTemplate 文档中的这一行
Note: by default the RestTemplate relies on standard JDK facilities to establish HTTP connections.
如果你查看Java中HttpUrlConnection
class的源代码,你会发现下面的代码块,headerOrigin
是一个禁止更改的受限 header 的数量:
/*
* Restrict setting of request headers through the public api
* consistent with JavaScript XMLHttpRequest2 with a few
* exceptions. Disallowed headers are silently ignored for
* backwards compatibility reasons rather than throwing a
* SecurityException. For example, some applets set the
* Host header since old JREs did not implement HTTP 1.1.
* Additionally, any header starting with Sec- is
* disallowed.
*
* The following headers are allowed for historical reasons:
*
* Accept-Charset, Accept-Encoding, Cookie, Cookie2, Date,
* Referer, TE, User-Agent, headers beginning with Proxy-.
*
* The following headers are allowed in a limited form:
*
* Connection: close
*
* See http://www.w3.org/TR/XMLHttpRequest2.
*/
private static final boolean allowRestrictedHeaders;
private static final Set<String> restrictedHeaderSet;
private static final String[] restrictedHeaders = {
/* Restricted by XMLHttpRequest2 */
//"Accept-Charset",
//"Accept-Encoding",
"Access-Control-Request-Headers",
"Access-Control-Request-Method",
"Connection", /* close is allowed */
"Content-Length",
//"Cookie",
//"Cookie2",
"Content-Transfer-Encoding",
//"Date",
//"Expect",
"Host",
"Keep-Alive",
"Origin",
// "Referer",
// "TE",
"Trailer",
"Transfer-Encoding",
"Upgrade",
//"User-Agent",
"Via"
};
这个问题有一个简单的修复方法,只需设置一个 JVM 参数
-Dsun.net.http.allowRestrictedHeaders=true
或在您的代码中添加一行
System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
取消限制。
有同样的问题。我发现 apache http 客户端没有这个问题并发送请求 'Origin': http://hc.apache.org/
HttpOptions httpOptions = new
HttpOptions(url)
httpOptions.setHeader("Origin", "test")
httpOptions.setHeader("Content-Type", "application/json")
BasicHttpClientConnectionManager manager = new
BasicHttpClientConnectionManager()
HttpClient client = new MinimalHttpClient(manager)
client.execute(httpOptions)