catalina.out日志
WARNING [http-nio-80-exec-2] org.glassfish.jersey.client.internal.HttpUrlConnector.setOutboundHeaders Attempt to send restricted header(s) while the [sun.net.http.allowRestrictedHeaders] system property not set. Header(s) will possibly be ignored.
原因:
jersey-client默认使用的是HttpUrlConnection来与jersey通信.它的allowRestrictedHeaders默认为false
/*
* 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"
};
源码查看:jdk/openjdk/7-b147的HttpURLConnection
private boolean isRestrictedHeader(String key, String value) {
if (allowRestrictedHeaders) {
return false;
}
key = key.toLowerCase();
if (restrictedHeaderSet.contains(key)) {
/*
* Exceptions to restricted headers:
*
* Allow "Connection: close".
*/
if (key.equals("connection") && value.equalsIgnoreCase("close")) {
return false;
}
return true;
} else if (key.startsWith("sec-")) {
return true;
}
return false;
}
初始化块:
static {
maxRedirects = java.security.AccessController.doPrivileged(
new sun.security.action.GetIntegerAction(
"http.maxRedirects", defaultmaxRedirects)).intValue();
version = java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("java.version"));
String agent = java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("http.agent"));
if (agent == null) {
agent = "Java/"+version;
} else {
agent = agent + " Java/"+version;
}
userAgent = agent;
validateProxy = java.security.AccessController.doPrivileged(
new sun.security.action.GetBooleanAction(
"http.auth.digest.validateProxy")).booleanValue();
validateServer = java.security.AccessController.doPrivileged(
new sun.security.action.GetBooleanAction(
"http.auth.digest.validateServer")).booleanValue();
enableESBuffer = java.security.AccessController.doPrivileged(
new sun.security.action.GetBooleanAction(
"sun.net.http.errorstream.enableBuffering")).booleanValue();
timeout4ESBuffer = java.security.AccessController.doPrivileged(
new sun.security.action.GetIntegerAction(
"sun.net.http.errorstream.timeout", 300)).intValue();
if (timeout4ESBuffer <= 0) {
timeout4ESBuffer = 300; // use the default
}
bufSize4ES = java.security.AccessController.doPrivileged(
new sun.security.action.GetIntegerAction(
"sun.net.http.errorstream.bufferSize", 4096)).intValue();
if (bufSize4ES <= 0) {
bufSize4ES = 4096; // use the default
}
//是否有设置
allowRestrictedHeaders = ((Boolean)java.security.AccessController.doPrivileged(
new sun.security.action.GetBooleanAction(
"sun.net.http.allowRestrictedHeaders"))).booleanValue();
//没有设置(默认为false),初始化restrictedHeaderSet
if (!allowRestrictedHeaders) {
restrictedHeaderSet = new HashSet<String>(restrictedHeaders.length);
for (int i=0; i < restrictedHeaders.length; i++) {
restrictedHeaderSet.add(restrictedHeaders[i].toLowerCase());
}
} else {
restrictedHeaderSet = null;
}
}
总结:
1.如果你的客户端请求中含有restrictedHeaders数组中定认的头标识,例如:
Client client = ClientBuilder.newClient();
System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
Response response = client.target(yourUri).path(yourPath).request().
header("Origin", "http://example.com").
header("Access-Control-Request-Method", "POST").
get();
上面的代码中Origin和Access-Control-Request-Method都是,如果不想看到警告,就像代码哪样设置:allowRestrictedHeaders,上面的代码取自:https://jersey.java.net/documentation/latest/client.html#d0e4320 官方的文档很全面的.
HttpUrlConnectorProvider uses HttpUrlConnection as an underlying connection implementation. This JDK class by default restricts the use of following headers:
Access-Control-Request-Headers
Access-Control-Request-Method
Connection (with one exception - Connection header with value Closed is allowed by default)
Content-Length
Content-Transfer-Encoding-Host
Keep-Alive
Origin
Trailer
Transfer-Encoding
Upgrade
Via
all the headers starting with Sec-
The underlying connection can be configured to permit all headers to be sent, however this behaviour can be changed only by setting the system property sun.net.http.allowRestrictedHeaders.
2.全局设置:jvm参数
-Dsun.net.http.allowRestrictedHeaders=true
3.除了默认的HttpURLConnection jersey-client还可以用?Apache Http Client
HttpClient apacheClient = HttpClientBuilder.create().build();
Client client = new Client(new ApacheHttpClient4Handler(apacheClient,
new BasicCookieStore(),
true));
WebResource webResource = client.resource("http://localhost:8080/path");
ClientResponse response = webResource.accept("application/json")
.get(ClientResponse.class);
如果服务端基于Https强烈建议使用HttpClient