【问题标题】:Setting Authorization header in XMLHttpRequest changes HTTP verb在 XMLHttpRequest 中设置 Authorization 标头会更改 HTTP 动词
【发布时间】:2015-12-16 01:58:56
【问题描述】:

今天发现 XMLHttpRequest 的一个奇怪行为。当我调用 GET 服务时,我发现如果我不设置 Authorization 标头,来自 firefox 的请求是相同的。但是,如果我添加“授权”标头 firefox 首先发送一个带有“OPTIONS”的请求,然后它会发送一个“GET”请求。

我知道动词“OPTIONS”必须在服务器端处理,但我只是想知道为什么 XMLHttpRequest 会这样。虽然是跨域请求,为什么浏览器要先发送“OPTIONS”请求。为什么添加“授权”标头会改变行为。

这是我的 Javascript 代码和 Fidler Inspector 报告。

    var  xmlhttp = new XMLHttpRequest();
    var url = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
    xmlhttp.open('GET',url,true);
    xmlhttp.setRequestHeader("Authorization", "xxxxxxxxxxxxxxxxxxx");
    xmlhttp.send(null);
    xmlhttp.onreadystatechange = function() {
            alert("OnReadystatechange + " + xmlhttp.readyState + " " + xmlhttp.status);
           if (xmlhttp.readyState == 4) {
              if ( xmlhttp.status == 200) {

                   }
                   else {

                   }
             }
             else
                   alert("Error ->" + xmlhttp.responseText);
          }

以及带有授权标头的提琴手响应

但是当我不添加 Authorization 标头时,浏览器直接发送 GET 请求 no OPTIONS 请求。

【问题讨论】:

    标签: javascript html firefox


    【解决方案1】:

    HTTP OPTIONS 请求用于在实际发送之前“预检”跨域 GET 请求。

    与简单请求不同,“预检”请求优先 通过 OPTIONS 方法向资源上的资源发送 HTTP 请求 其他域,以判断实际请求是否安全 发送。跨站点请求是这样预检的,因为它们可能 对用户数据有影响。特别是,请求是 预检如果:

    • 它使用 GET、HEAD 或 POST 以外的方法。此外,如果 POST 用于发送 Content-Type 不是
      的请求数据 application/x-www-form-urlencoded、multipart/form-data 或
      文本/纯文本,例如如果 POST 请求将 XML 有效负载发送到
      服务器使用 application/xml 或 text/xml,那么请求是
      预检。
    • 它设置任何不被认为是简单的标头。如果标头字段名称是 Accept 的不区分大小写的 ASCII 匹配,则称标头为简单标头>Accept-Language,或 Content-Language,或者如果它是 Content-Type 和标头字段值媒体类型(不包括parameters) 是 application/x-www-form-urlencodedmultipart/form-datatext/plain 的 ASCII 大小写不敏感匹配>.

    因此,在您的情况下,设置 Authorization 标头会导致请求被预检,因此是 OPTIONS 请求。

    More info here

    Spec on Cross-Origin Request with Preflight

    【讨论】:

    • 是的,我了解预检请求。但只是想知道为什么添加授权标头会产生预检请求。这里没有满足这两个要求(如链接中所述)。
    • 授权标头符合custom header。见第二个要求。
    • 看来是这样。否则没有任何意义。我认为这个标头是一个标准标头,因为它提到了here。无论如何,非常感谢您提供的信息。我是 Javascript 的新手。您提到的链接确实帮助我理解了预检请求。
    • 我也不明白为什么授权在 CORS 的上下文中被视为“自定义标头”,而它显然是 http protocol 的一部分。这意味着在您使用令牌身份验证的 CORS 场景中(我认为这在任何 CORS 场景中都是一种最佳实践),基本上 每个 请求,包括所有简单的 GET 请求都将被预先发送并作为结果需要更长的时间。
    • @VincentSels 初始预检请求的结果可以被浏览器缓存,具体取决于响应头Access-Control-Max-Age的值。
    猜你喜欢
    • 2021-03-27
    • 1970-01-01
    • 2012-01-17
    • 2017-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-01
    • 1970-01-01
    相关资源
    最近更新 更多