JavaScript 的同源策略

在 JavaScript 中,我们可以用 XMLHttpRequest 对象在后台和服务器交换数据。XMLHttpRequest 是 AJAX 的基础之一。但是由于 JavaScript 的同源策略的限制,在网页和第三方网站交互时,无法这样使用。在许多网站纷纷开放 API 的今天,这个限制真是让人恼火。

还好,W3C 已经提出了跨源资源共享(Cross-Origin Resource Sharing)协议,而且 IE 8+,Firefox 3.5+,Chrome 4+,Safari 4+,Opera 12+ 都支持这种方式。其中 IE8 和 IE9 使用  XDomainRequest 对象,而其它浏览器依然使用 XMLHttpRequest 对象进行跨源通信。 但是,要能使用这种协议,需要第三方网站在 HTTP 头中设置 Access-Control-Allow-Origin 项,这导致目前这种方式经常不可用。

其它凑合的方法也有。比如可以利用 script.src 可以跨源的特点来获取第三方资源。这种方式通常和 JSONP(JSON with Padding)一起使用,利用 JSON 作为数据格式,用 script.src 中的 callback 参数来进行回调处理。第三方服务器端的 PHP 代码类似于这样:

$json = json_encode($mydata);
 
// Using JSONP
if ($_GET['callback']) {
    echo $_GET['callback'] . "($json);";

// Normal JSON
} else {
    echo $json;
}

这种方式同样需要第三方网站支持,例如很多提供 RESTful Web API 的网站都是支持 JSONP 方式的。但是最大的限制在于,这种方式只能用 GET 方式获取数据。

如果要用 POST 方式提交数据,可以用表单(form)的 POST 方式,这是因为表单提交也是可以跨源的。用这种方式还需要用 JavaScript 禁止提交成功后的页面跳转。

最后,HTML5 中还提供了 postMessage 的方式用于跨文档通信(cross-document messaging)。你可以用 iframe 加载另一个域名的页面,然后两者之间用 postMessage 和 message 事件实现互相交换数据。

参考资料:

[1] Same origin policy - Wikipedia
[2] Cross-Origin Resource Sharing - W3C
[3] HTTP access control (CORS) - MDN
[4] When can I use Cross-Origin Resource Sharing?
[5] enable cross-origin resource sharing
[6] Javascript:使用Web代理实现XMLHttpRequest跨域访问
[7] Cross-domain AJAX with JSONP - Devlog
[8] JSONP跨域的原理解析
[9] Using PUT/POST/DELETE with JSONP and jQuery
[A] window.postMessage - MDN
[B] 利用HTML5的window.postMessage实现跨域通信
[C] HTML5:使用postMessage实现Ajax跨域请求
[D] easyXDM - Cross-domain messaging made easy

原文地址:https://www.cnblogs.com/zoho/p/2559192.html