【问题标题】:RestTemplate not passing Origin headerRestTemplate 未传递 Origin 标头
【发布时间】:2017-01-17 14:24:48
【问题描述】:

我正在尝试使用 Spring 的 RestTemplate 发出跨域请求。通信是在两个 Spring-boot webapps 之间完成的,它们都运行在 localhost 但不同的端口上。我要做的是:

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”标头通过就好了,但无论我尝试什么,接收端都没有“Origin”标头。 当我使用其他工具(SoapUI、RestClient Chrome 插件等)创建类似请求时,标头会按照我提供的方式传递。

为了在接收端打印所有标题,我使用了 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?

【问题讨论】:

    标签: java spring spring-mvc resttemplate


    【解决方案1】:

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

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

    注意:默认情况下,RestTemplate 依赖于标准 JDK 工具来建立 HTTP 连接。

    如果您检查 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");
    

    抑制限制。

    【讨论】:

      【解决方案2】:

      有同样的问题。我发现 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)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-21
        • 2021-11-27
        • 2016-08-25
        • 1970-01-01
        • 2021-03-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多