CORS问题:预检的响应具有无效的HTTP状态代码403

时间:2018-04-19 14:50:56

标签: angularjs spring-mvc cors

环境 Tomcat Server托管webservice应用程序。 网站是使用SpringMVC和AngularJS构建的。

核心问题: REST GET触发OPTIONS请求,该请求失败。 有问题的GET返回应用程序/ JSON响应。 最初,我收到了错误:

"无法加载资源:服务器响应状态为403(禁止)

  

无法加载http://myServer:8084/wsPRDE/navbar/getnavbartxt:对预检请求的响应未通过访问控制检查:否' Access-Control-Allow-Origin'标头出现在请求的资源上。起源' http://myServer:8080'因此不允许访问。响应的HTTP状态代码为403。"

在此问题出现之前,我们所做的只是在控制器中使用@CrossOrigin。然后设置httpd.conf来添加这些标头。这对于从站点检索的所有脚本(具有讽刺意味的不是CORS)而不是实际的CORS响应。当我确保在响应中返回Access-Control-Allow-Origin,Allow-Methods和Allow-Headers时,通过将CORSFilter编码到Web服务中,错误更改为:

  

"选项http://myServer:8084/wsPOFA/navbar/getnavbartxt 403(禁止)   无法加载http://myServer:8084/wsPOFA/navbar/getnavbartxt:预检的响应包含无效的HTTP状态代码403."

背景 以相当随机的方式检测到错误。 我的流程管理同事有一个Windows 10更新。 自上述更新以来,整个Web服务失败,因为无法访问。从站点本身到Web应用程序(相同地址,不同端口)的任何请求都会失败。我的上级(我是实习生)然后发现在Chrome和IE中(当使用服务器别名时,而不是在使用"普通" URL时)在没有Windows 10更新的情况下具有相同的问题。在更新之前(或使用具有普通URL的IE),GET似乎不会触发OPTIONS请求。

进一步尝试在此之后,我尝试展开Allow-Headers以包含GET请求/响应中的所有字段。我还将OPTIONS请求中的Origin与Origins的白名单进行比较,将OPTIONS响应Allow-Origin标头值设置为请求Origin值(如果它们匹配)。

因此,起源匹配并且请求/响应中的所有标头都被设置为允许。到目前为止,我花了3天时间阅读CORS并在网上寻找解决方案。大多数解决方案都提到了我已实现的CORS过滤器,然后完全清除标头有大量的脏处理方法,总是对OPTIONS请求响应200 OK。但他们看起来很肮脏"的解决方案。

有人能指出我正确的方向吗?我应该考虑向我的Spring控制器添​​加与CORS相关的代码吗?向AngularJS构建httpRequests的委托是我问题的关键吗?还是我完全在想错误的方向?

目前,我的请求/响应标头如下所示: Headers

1 个答案:

答案 0 :(得分:0)

这个问题被低估了,可能是因为当我决定寻求帮助时,我并没有完全清楚。无论如何,我今天设法解决了这个问题。当我发布问题时,我已经在应用程序级别创建了自定义CORS过滤器。如果设置了Allow-Origin和Allow-Methods字段并且仅对非选项请求应用chain.doFilter(),则更改此过滤器以手动将“状态代码”设置为“200”以解决此问题。我不确定它是否是理想/安全的解决方案。但它的确有效。您可以在下面找到所使用的完整解决方案。

的web.xml:

<filter>
    <filter-name>SimpleCORSFilter</filter-name>
    <filter-class>com.ofis.webservice.CORS.SimpleCORSFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>SimpleCORSFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

过滤类:

package com.ofis.webservice.CORS;

import java.io.IOException;
import java.util.ArrayList;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SimpleCORSFilter implements Filter {

    ArrayList<String> AllowedOrigins;
    ArrayList<String> AllowedMethods;

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
    if (request.getMethod().equals("OPTIONS")) {
        String reqOrigin;
        reqOrigin = request.getHeader("Origin");

        for (String origin : AllowedOrigins) {
            if (origin.equals(reqOrigin)) {
                response.setHeader("Access-Control-Allow-Origin", reqOrigin);
                break;
            }
        }

        String reqMethod;
        reqMethod = request.getHeader("Access-Control-Request-Method");

        for (String method : AllowedMethods) {
            if (method.equals(reqMethod)) {
                response.setHeader("Access-Control-Allow-Method", reqMethod);
            }
        }

        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Headers", "cache-control,if-modified-since,pragma,Content-Type");

        //Checks if Allow-Method and Allow-Origin got set. 200 OK if both are set.
        if(!response.getHeader("Access-Control-Allow-Method").equals("") && !response.getHeader("Access-Control-Allow-Origin").equals("")){
            response.setStatus(200);
        }
    } else {
        chain.doFilter(req, res);
    }