首页 文章

为什么这个CORS请求仅在Firefox中失败?

提问于
浏览
12

我有点迷惑为什么预检请求在Firefox 30中一直失败但在Safari(7.0.2)和Chrome 35中有效 . 我认为这个问题与“Why does the preflight OPTIONS request of an authenticated CORS request work in Chrome but not Firefox?”有所不同,因为我没有获得401,而是一个CORS-来自浏览器客户端的特定消息:

“跨源请求已阻止:同源策略不允许在http://myurl.dev.com上读取远程资源 . 可以通过将资源移动到同一域或启用CORS来修复此问题 . ”

没有显示源代码,这就是我正在做的事情:

On the server

OPTIONS响应的 Headers :

  • Access-Control-Allow-Origin:[[来自请求的原点]]

  • 访问控制 - 允许 - 方法:"POST GET OPTIONS"

  • Access-Control-Allow-Headers:"X-Requested-With"

  • Access-Control-Allow-Credentials:"true"

POST响应的 Headers :

  • Access-Control-Allow-Origin:[[来自请求的原点]]

  • Access-Control-Allow-Credentials:"true"

In the browser client:

jQuery.ajax({
  url: requestUrl,
  type: 'POST',
  data: getData(),
  xhrFields: {
    withCredentials: true
  }
});

根据规范,这将触发OPTIONS预检请求,该请求需要在其响应中具有CORS头 . 我已经多次阅读过W3C规范了,在预检响应中我无法确定我做错了什么,如果有的话 .

2 回答

  • 8

    请注意,Firefox是唯一符合此处的浏览器 . 如果按https://fetch.spec.whatwg.org/#cors-preflight-fetch解析 Access-Control-Allow-Methods 失败,则需要返回网络错误 . 并且根据 Headers 值的ABNF,它绝对是逗号分隔值 .

  • 0

    我注意到当你发送带有cookie设置的CORS(跨源资源共享)请求时,Firefox不会发送所需的响应头 .

    Solution:

    以下解决方案仅为OPTIONS请求添加标头,仅接受来自example.com的请求 . 您可以更改其他请求方法和预期主机的实现 .

    JS CODE

    var xmlhttp = new XMLHttpRequest();
    xmlhttp.withCredentials = true;
    
    xmlhttp.onreadystatechange = function () {
        if (xmlhttp.readyState == XMLHttpRequest.DONE) {
            if (xmlhttp.status == 200) {
                success_callback(xmlhttp.responseText);
            } else {
                error_callback(xmlhttp.statusText);
            }
        }
    };
    xmlhttp.open("DELETE", url);
    xmlhttp.send(null);
    

    当您发送DELETE请求时,浏览器会发送OPTIONS的转发前请求,该请求在响应标头中需要 Access-Control-Allow-Methods . 根据此标头值,发送实际的DELETE请求 . 在Firefox中,当您发送DELETE请求时,飞行前请求的响应标头没有预期的标头,因此无法发送实际的DELETE请求 .

    要解决此问题,请使用以下NGINX服务器配置 .

    NGINX CODE

    #handle CORS requests by adding required headers
    if ($http_origin ~* .example.com) {
        set $cors "CORS-${request_method}";
    }
    
    if ($cors = "CORS-OPTIONS") {
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Headers' 'Content-Type';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE';
        add_header 'Access-Control-Allow-Origin' $http_origin;
    }
    

    关于CORS的好读物:https://www.html5rocks.com/en/tutorials/cors/

相关问题