靠谱的软件下载站
当前位置:  IEfans/IE专区/IE相关/IE10中的CORS for XHR

IE10中的CORS for XHR

IE相关 互联网 2012-02-24 阅读(6787)

IE10 平台预览第四版支持用于 XMLHttpRequest (XHR) 的跨域资源共享 (CORS), 从而简化了可跨浏览器一致运行的跨网站方案的构建过程。CORS for XHR 使跨网站共享数据变得简单而灵活。在最基本的方案中,CORS 允许创建可从任意网站访问的数据源,并且只需稍做调整,即可限制允许的网站,支持数据修改,甚至允许身份验证。最重要的是,CORS 可通过要求服务器参与来保护现有网站的安全。

简单的跨域 XHR

我们来看一下跨域 XHR 请求与同域请求相比有何区别。就脚本而言,唯一的区别在于传递到 open 方法的 URL。例如,假设我们要编写一个获取相册列表的脚本。

传统 XHR

// Script running on http://photos.contoso.com

var xhr = new XMLHttpRequest();

xhr.onerror = _handleError;

xhr.onload = _handleLoad;

xhr.open("GET", "/albums", true);

xhr.send();

现在,我们希望从另一个域访问相册列表。另一个域可以是完全不同的域,也可以是具有相同基域的不同主机。无论是哪种情况,只需要从另一个网站指向完整 URL,浏览器就会自动发送 CORS 请求。

支持 CORS 的 XHR

// Script running on http://www.contoso.com

var xhr = new XMLHttpRequest();

xhr.onerror = _handleError;

xhr.onload = _handleLoad;

xhr.open("GET", "http://photos.contoso.com/albums", true);

xhr.send();

网站可以通过在功能检测中包含对回退功能的检测,为旧浏览器提供回退功能。最佳做法是检查“withCredentials”,因为它直接与 XHR 的 CORS 支持相关。

支持 CORS 且具备功能检测能力的 XHR

// Script running on http://www.contoso.com

var xhr = new XMLHttpRequest();

if ("withCredentials" in xhr) {

xhr.onerror = _handleError;

xhr.onload = _handleLoad;

xhr.open("GET", "http://photos.contoso.com/albums", true);

xhr.send();

} else {

// Fallback behavior for browsers without CORS for XHR

}

此时,我们的客户端代码直接向“http://photos.contoso.com”发出 CORS 请求,但该请求未返回任何数据。失败的原因在于服务器尚未参与其中。快速查看一下开发工具就可以发现是哪个环节出现问题。

F12 工具的屏幕截图,图中显示未找到“Access-Control-Allow-Origin”标头。

我们可以从中看出服务器需要在响应中发送“Access-Control-Allow-Origin”标头。在我们的方案中,我们没有打开相册供任何网站访问,而是希望只允许从“http://www.contoso.com”进行访问。为此,需要允许服务器识别发出请求的位置。检查我们发出的请求可以发现,新标头中明确地包含有“Origin”这一信息。

简单的 CORS 请求标头

GET http://photos.contoso.com/albums HTTP/1.1

Origin: http://www.contoso.com

...

通过使用此信息,服务器可以选择将访问权限限制为任意一组网站。如果服务器始终添加值为“*”的“Access-Control-Allow-Origin”标头,则所有网站均具有访问权限。在我们的方案中,我们会让服务器验证域,然后设置“Access-Control-Allow-Origin”以便仅允许“http://www.contoso.com”。

简单的 CORS 响应标头

HTTP/1.1 200 OK

Access-Control-Allow-Origin: http://www.contoso.com

...

进行上述更新后,我们的“http://www.contoso.com”客户端现在就可以从服务器访问位于“http://photos.contoso.com”中的相册列表了。

带预检功能的跨域 XHR

到目前为止,我们所讨论的“简单”CORS 请求非常适合基本的只读方案,如下载相册。如需采取下一步操作以便跨网站修改数据,则要求在服务器上完成更多工作。例如,假设我们要在客户端中添加相应代码以创建一个新相册。

var xhr = new XMLHttpRequest();

xhr.onerror = _handleError;

xhr.onload = _handleLoad;

xhr.open("PUT", "http://photos.contoso.com/albums", true);

xhr.send(JSON.stringify({ name: "New Album" }));

按原样运行上述代码不起作用。通过检查网络流量可以发现,请求已发送,但不是我们预期的请求。

F12 工具的屏幕截图,图中显示了 OPTIONS 预检请求。

浏览器实际发送的内容称为预检请求。预检请求在可能导致服务器上发生数据修改的请求之前发送。可根据是否存在 CORS 规范中定义的非简单属性来识别此类请求。这些属性可以是诸如“PUT”之类的特定 HTTP 方法,也可以是自定义的 HTTP 标头。浏览器发送预检请求的目的是要求服务器允许发送实际请求。在我们的示例中,浏览器验证是否允许“PUT”请求。

预检请求

OPTIONS http://photos.contoso.com/albums HTTP/1.1

Origin: http://www.contoso.com

Access-Control-Request-Method: PUT

...

让浏览器发送实际请求需要在服务器上进行一些更改。同样,我们可以看一下开发工具以了解详细信息。

F12 工具的屏幕截图,图中显示未找到“Access-Control-Allow-Methods”列表。

第一步是让服务器意识到“OPTIONS”预检请求与针对同一 URL 的其他请求有所不同。服务器通过确保“Access-Control-Request-Method”是从允许的域请求“PUT”来验证预检请求,之后,它会通过“Access-Control-Allow-Methods”标头发送相应的批准信息。

预检响应

HTTP/1.1 200 OK

Access-Control-Allow-Origin: http://www.contoso.com

Access-Control-Allow-Methods: PUT

...

预检完成并得到批准后,即会发出实际的请求。

实际请求

PUT http://photos.contoso.com/albums HTTP/1.1

Origin: http://www.contoso.com

...

从技术层面上讲,添加相册的操作到此已经完成,不过,在服务器发出正确响应之前,我们的客户端代码并不知道这一信息。具体说就是,服务器仍然必须在响应中包含“Access-Control-Allow-Origin”。

实际响应

HTTP/1.1 200 OK

Access-Control-Allow-Origin: http://www.contoso.com

...

这样一来,客户端就可以跨域添加新的相册,并识别该操作是否成功完成。

后续步骤

将 CORS 与其他新增平台功能搭配使用可创建引人入胜的方案。例如,跨网站上载体验可以利用 CORS、XHR、FileAPI 和进程事件来跟踪跨域文件上载操作。

—Internet Explorer 项目经理 Tony Ross

英文原文:CORS for XHR in IE10

标签:IE10IE WebCORSXHR

Copyright © 1998-2017 www.iefans.net All Rights Reserved 湘ICP备13012168号-17