java - RestTemplate 不传递 Origin header

标签 java spring spring-mvc resttemplate

我正在尝试使用 Spring 的 RestTemplate 发出跨源请求。通信是在两个 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 将按照我提供的方式传递。

为了在接收方打印所有 header ,我使用了 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 时没有传递 origin header?

最佳答案

有同样的问题,我花了一个世纪来解决。

根本原因是 RestTemplate 文档中的这一行

Note: by default the RestTemplate relies on standard JDK facilities to establish HTTP connections.

如果你查看 Java 中的 HttpUrlConnection 类的源代码,你会发现下面的代码块,标题 Origin 是禁止更改的受限标题之一:

/*
 * 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");

抑制限制。

关于java - RestTemplate 不传递 Origin header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41699608/

相关文章:

java - 如何在 Spring MVC 中监视执行器或其他任务执行线程

java - Spring MVC - 当休息 Controller 响应类型为空时自动返回 204

java - 在没有其他模块提供该实例的情况下提供实例

java - 我可以将 Room Persistence Library 用于 Java 桌面应用程序吗?

spring - 为什么我需要 cglib (Spring AOP) 来拥有多个测试类?

java - 我应该用@NonNull 注释标记接口(interface)及其实现吗?

spring - 在多模块 Java-Config Spring MVC 应用程序中使用 @ComponentScan 的正确方法

java - 所有 RuntimeException/Un-checked 异常的拥护者,你们会如何处理这种情况?

java - 表单选项未填充

java - Spring框架无法启动嵌入式容器