IE10 的第四个平台简化了构建跨站点场景的跨浏览器一直工作,通过支持跨起源资源共享 (麦子)的起始地址 (XHR)。简单、 灵活,XHR 的麦子使跨站点共享的数据。在最基本的情况下麦子使创建数据源,可以从任何站点,访问,并与几个小改动,您可以选择限制允许的网站,支持数据修改,并甚至允许身份验证。最重要的是麦子保持现有网站安全通过要求服务器参与。
简单跨起源 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 就足以让浏览器自动发送麦子的请求。
麦子启用 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 的麦子支持。
麦子启用 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",但是,请求将失败,返回任何数据。因为服务器不加入尚未出现故障。看看开发者工具快速给了我们一个错就错的想法。
在这里我们可以看到,服务器需要发送响应中的"Access-Control-Allow-Origin
"标头。在我们的方案我们不开放我们任何网站访问,但是想启用访问单从"http://www.contoso.com
"的专辑。此操作需要允许服务器以确定发出请求。检查我们传出的请求揭示了一个新的标头包含正是此信息,"Origin
"。
简单的麦子请求标头
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
"。
简单的麦子响应标头
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://www.contoso.com
...
在地方,上述更新,我们的"http://www.contoso.com
"客户端现在可以从"http://photos.contoso.com
"在服务器访问相册列表。
印前检查与跨起源 XHR
"简单"的麦子请求为止讨论是很好的基础,只读的情况下,如下载相册等。通过跨站点修改数据采取下一步需要在服务器上的更多工作。例如,我们在客户端创建新专辑中加入了代码。
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" }));
运行此作为-是不起作用。检查网络通信量,揭示了发送一个请求,但我们预期不会。
什么浏览器实际发送被称为一个印前检查的请求。印前检查请求发送之前可能会导致服务器上的数据修改的请求。麦子规范中定义的非简单属性存在标识此类请求。这些属性范围从某些 HTTP 方法想"PUT
"自定义 HTTP 标头。浏览器发送印前检查请求,请求服务器发送实际要求的权限。在我们的示例中,浏览器验证允许"PUT
"的请求。
印前检查的请求
OPTIONS http://photos.contoso.com/albums HTTP/1.1
Origin: http://www.contoso.com
Access-Control-Request-Method: PUT
...
要获得实际的请求发送到浏览器需要一些服务器上的更改。再一次我们可以看看的开发工具的详细信息。
第一步是将认识到相同的 URL 有别于其他请求"OPTIONS
"印前检查请求的服务器。通过确保"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
...
与客户端可以添加新专辑跨原点,并确认已成功完成该操作。
接下来的步骤
与其他新的平台功能配对麦子使有趣的情形。跨站点上传试驾跟踪跨起源文件上载使用麦子、 XHR、 FileAPI 和进度事件就是一例。
— — 托尼 · 罗斯,程序管理器、 Ie 浏览器