【问题标题】:CORS issue on java web applicationJava Web应用程序上的CORS问题
【发布时间】:2016-03-29 19:37:05
【问题描述】:

后端由Spring MVC开发,托管在tomcat中。

当我在 Chrome 中使用 postman 开发工具测试端点(Restful)时,一切正常。 “Access-Control-Allow-Origin”、“*”成功添加到服务器。像下面的截图

但是当我编写 Ajax 时提出了同样的要求。因为浏览器有 Origin Policy(postman 没有这个策略),它会先向服务器发送一个 HTTP OPTIONS 请求头来判断实际请求是否可以安全发送。像下面的截图。

响应头与我从邮递员那里得到的完全不同,并且头中没有“Access-Control-Allow-Origin”,“*”。我认为服务器无法接受选项请求。

我试图通过查看此链接在 tomcat web.xml 中添加过滤器:http://enable-cors.org/server_tomcat.html

只有使用没有 Origin 策略的开发工具(如 curl 和 postman)才能完美运行。但它不适用于 Ajax 浏览器。

请看下面的过滤器类

public class SimpleCORSFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
System.out.println("test123");
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
        chain.doFilter(req, res);
    }
    public void init(FilterConfig filterConfig) {}
    public void destroy() {}
}

我在过滤器中使用System.out.println("test123");,当使用邮递员或curl时,它在控制台中打印了'test123',但在使用浏览器时没有打印,所以我猜是浏览器发送了OPTIONS请求,并且过滤器没有拦截它,或者其他东西首先拦截了来自浏览器的请求?

谁能帮帮我?谢谢。

【问题讨论】:

  • 您可以尝试在响应标头中添加Access-Control-Allow-Credentials: true
  • 也尝试设置Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token"

标签: javascript spring-mvc tomcat cross-domain cors


【解决方案1】:

如果您使用的是 tomcat,则可以在 web.xml 中包含 tomcat's implementaion

<filter>
  <filter-name>CorsFilter</filter-name>
  <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>CorsFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

或者在我的应用程序中,我做了一个过滤器(更新),如下所示:

public class CorsFilter implements Filter {


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, HEAD, OPTIONS");
        response.setHeader("Access-Control-Allow-Headers", "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
      if ("OPTIONS".equalsIgnoreCase((HttpServletRequest) servletRequest.getMethod())) {
        response.setStatus(HttpServletResponse.SC_OK);
      } else {
         filterChain.doFilter(servletRequest, response);
      }

    }

    @Override
    public void destroy() {

    }
}

另外请注意,您不应该使用 Spring 的注释来注释过滤器类,例如 @Component

或者更好的是你可以使用Spring's CORS support

【讨论】:

  • 嗨,Tom,我按照您说的更改了过滤器。它在邮递员中显示正确的标题,但仍然无法在浏览器中工作。 OPTIONS 请求的响应没有正确的标头。截图:prntscr.com/9hmpzr postman 中的响应头是:prntscr.com/9hmr5x 在 postman 中工作
  • @Xiang 要确认它的浏览器来源策略,如果您使用的是 Chrome,您可以添加任何启用 CORS 的扩展程序并尝试 AJAX。这不是仅仅确认发现或存在任何问题的解决方案ajax 请求
  • @Xiang 这里是一个类似的问题。可能它可以帮助stackoverflow.com/questions/30632200/…。答案中的更新相同
  • 有人找到解决这个问题的方法吗?我也面临同样的问题。
  • 是的,最后,我只需要将此标头 response.setHeader("Access-Control-Allow-Origin", "*") 添加到 servlet 即可。问题是当我从 Javascript/浏览器测试 servlet 时,我传递了额外的不必要的标头 Authorization 代码。当我删除这部分时,它立即起作用。诀窍是在 Javascript 中使用简单/最少的代码来测试 servlet。我将var request = new XMLHttpRequest();get 和简单的URL 一起使用,效果很好。
【解决方案2】:

使用response.setHeader("Access-Control-Allow-Origin", "*"); 不管用。 您需要输入明确的请求 URL。 从请求到 servlet 的来源,并在每个请求上动态替换。

这是我用来解决这个问题的代码sn-p:

    String clientOrigin = request.getHeader("origin");
    response.setHeader("Access-Control-Allow-Origin", clientOrigin);
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Credentials", "true");
    response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Access-Control-Allow-Origin,CopyStreamException,Access-Control-Allow-Methods,Access-Control-Max-Age");

编辑 1: 我再次查看了我的代码,发现我还在我的 web.xml 中添加了过滤器,正如@Tom-Sebastian 所提到的那样

这是我在 web.xml 中的内容:

<filter>
    <filter-name>CORS</filter-name>
    <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>CORS</filter-name>
    <servlet-name>myServlet</servlet-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

希望对你有所帮助,
利隆

【讨论】:

  • 感谢 Liron,我尝试了您的解决方案,不幸的是仍然无法正常工作。
  • 嗨,我好像错过了一部分(web.xml 过滤器)并更新了我的答案检查是否有帮助。
猜你喜欢
  • 1970-01-01
  • 2011-04-20
  • 1970-01-01
  • 2017-01-04
  • 1970-01-01
  • 2010-09-18
  • 2022-10-01
  • 2013-04-05
  • 1970-01-01
相关资源
最近更新 更多