为什么经过身份验证的 CORS 请求的预检 OPTIONS 请求在 Chrome 中有效,但在 Firefox 中无效? [英] Why does the preflight OPTIONS request of an authenticated CORS request work in Chrome but not Firefox?

查看:26
本文介绍了为什么经过身份验证的 CORS 请求的预检 OPTIONS 请求在 Chrome 中有效,但在 Firefox 中无效?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个 JavaScript 客户端以包含在 3rd 方网站上(想想 Facebook Like 按钮).它需要从需要基本 HTTP 身份验证的 API 中检索信息.简化的设置如下所示:

I am writing a JavaScript client to be included on 3rd party sites (think Facebook Like button). It needs to retrieve information from an API that requires basic HTTP authentication. The simplified setup looks like this:

第 3 方网站在其页面上包含此代码段:

A 3rd party site includes this snippet on their page:

<script 
async="true"
id="web-dev-widget"
data-public-key="pUbl1c_ap1k3y"
src="http://web.dev/widget.js">
</script>

widget.js 调用 API:

var el = document.getElementById('web-dev-widget'),
    user = 'token',
    pass = el.getAttribute('data-public-key'),
    url = 'https://api.dev/',
    httpRequest = new XMLHttpRequest(),
    handler = function() {
      if (httpRequest.readyState === 4) {
        if (httpRequest.status === 200) {
          console.log(httpRequest.responseText);
        } else {
          console.log('There was a problem with the request.', httpRequest);
        }
      }
    };

httpRequest.open('GET', url, true, user, pass);
httpRequest.onreadystatechange = handler;
httpRequest.withCredentials = true;
httpRequest.send();

API 已配置为使用适当的标头进行响应:

The API has been configured to respond with appropriate headers:

Header set Access-Control-Allow-Credentials: true
Header set Access-Control-Allow-Methods: "GET, OPTIONS"
Header set Access-Control-Allow-Headers: "origin, authorization, accept"
SetEnvIf Origin "http(s)?://(.+?.[a-z]{3})$" AccessControlAllowOrigin=$0
Header set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin

请注意,Access-Control-Allow-Origin 设置为 Origin 而不是使用通配符,因为我正在发送一个有凭据的请求 (withCredentials).

Note that the Access-Control-Allow-Origin is set to the Origin instead of using a wildcard because I am sending a credentialed request (withCredentials).

现在一切就绪,可以发出异步跨域身份验证请求,并且在 OS X 10.8.2 上的 Chrome 25 中运行良好.在 Dev Tools 中,我可以在 GET 请求之前看到 OPTIONS 请求的网络请求,并且响应按预期返回.

Everything is now in place to make an asynchronous cross-domain authenticated request, and it works great in Chrome 25 on OS X 10.8.2. In Dev Tools, I can see the network request for the OPTIONS request before the GET request, and the response comes back as expected.

在 Firefox 19 中测试时,Firebug 中没有出现对 API 的网络请求,并在控制台中记录此错误:NS_ERROR_DOM_BAD_URI: Access to Restricted URI denied

When testing in Firefox 19, no network requests appear in Firebug to the API, and this error is logged in the console: NS_ERROR_DOM_BAD_URI: Access to restricted URI denied

经过多次挖掘,我发现 Gecko 没有根据评论,允许用户名和密码直接在跨站 URI 中.我认为这是从使用可选的用户和密码参数到 open() 所以我尝试了另一种发出经过身份验证的请求的方法,即对凭据进行 Base64 编码并在授权标头中发送:

After much digging, I found that Gecko doesn't allow the username and password to be directly in a cross-site URI according to the comments. I assumed this was from using the optional user and password params to open() so I tried the other method of making authenticated requests which is to Base64 encode the credentials and send in an Authorization header:

// Base64 from http://www.webtoolkit.info/javascript-base64.html
auth = "Basic " + Base64.encode(user + ":" + pass);

...
// after open() and before send()
httpRequest.setRequestHeader('Authorization', auth);

这会导致对 OPTIONS 请求的 401 Unauthorized 响应导致 Google 搜索,例如为什么这适用于 Chrome 而不是 Firefox!?"那时我才知道我遇到了麻烦.

This results in a 401 Unauthorized response to the OPTIONS request which lead to Google searches like, "Why does this work in Chrome and not Firefox!?" That's when I knew I was in trouble.

为什么 它适用于 Chrome 而不是 Firefox?如何让 OPTIONS 请求一致地发送和响应?

Why does it work in Chrome and not Firefox? How can I get the OPTIONS request to send and respond consistently?

推荐答案

为什么 它适用于 Chrome 而不是 Firefox?

Why does it work in Chrome and not Firefox?

针对 CORS 预检请求的 W3 规范明确指出用户应排除凭据.ChromeWebKit 其中 OPTIONS 请求返回 401 状态仍然发送后续请求.

The W3 spec for CORS preflight requests clearly states that user credentials should be excluded. There is a bug in Chrome and WebKit where OPTIONS requests returning a status of 401 still send the subsequent request.

Firefox 提交了一个相关的错误,该错误以指向 W3 公共网络应用邮件列表,要求采用 CORS 规范更改为允许在 OPTIONS 请求上发送身份验证标头,以有利于 IIS 用户.基本上,他们在等待这些服务器被淘汰.

Firefox has a related bug filed that ends with a link to the W3 public webapps mailing list asking for the CORS spec to be changed to allow authentication headers to be sent on the OPTIONS request at the benefit of IIS users. Basically, they are waiting for those servers to be obsoleted.

如何让 OPTIONS 请求一致地发送和响应?

How can I get the OPTIONS request to send and respond consistently?

只需让服务器(在本例中为 API)响应 OPTIONS 请求而无需身份验证.

Simply have the server (API in this example) respond to OPTIONS requests without requiring authentication.

Kinvey 做得很好工作扩展于此,同时还链接到 Twitter API 的一个问题 在任何浏览器问题被提交前几周有趣地概述了这个确切场景的 catch-22 问题.

Kinvey did a good job expanding on this while also linking to an issue of the Twitter API outlining the catch-22 problem of this exact scenario interestingly a couple weeks before any of the browser issues were filed.

这篇关于为什么经过身份验证的 CORS 请求的预检 OPTIONS 请求在 Chrome 中有效,但在 Firefox 中无效?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆