我想做一个关于 HTML/JS 原产地相同的政策的社区 wiki,希望能帮助任何人搜索这个主题。这是 SO 上搜索次数最多的主题之一,目前还没有统一的 wiki,所以我在这里介绍一下:)
相同的原点策略可以防止 从一个文件或脚本加载 来源于获得或设置 来自另一个文档的属性 这份保单的日期一直都是 回到2.0网景导航者。
请保持例子详细,最好也链接您的来源。
就个人而言,window.postMessage是我为现代浏览器找到的最可靠的方法。您确实需要多做一点工作,以确保不会让自己受到 XSS 攻击,但这是一个合理的权衡。
window.postMessage
还有一些用于流行的 Javascript 工具包的插件包装了 window.postMessage,它们使用上面讨论的其他方法提供了与旧浏览器类似的功能。
在服务器上设置一个简单的 反向代理服务器,将允许浏览器使用 Ajax 请求的相对路径,而服务器将充当任何远程位置的代理。
如果在 Apache 中使用 Mod _ proxy,则设置反向代理的基本配置指令是 ProxyPass。它的典型用法如下:
ProxyPass
ProxyPass /ajax/ http://other-domain.com/ajax/
在这种情况下,浏览器将能够请求 /ajax/web_service.xml作为一个相对 URL,但是服务器将通过充当 http://other-domain.com/ajax/web_service.xml的代理来实现这一点。
/ajax/web_service.xml
http://other-domain.com/ajax/web_service.xml
此方法的一个有趣特性是,反向代理可以轻松地将请求分发到多个后端,从而充当 负载平衡器。
我用的是 JSONP。
基本上,你加上
<script src="http://..../someData.js?callback=some_func"/>
在你的页面上。
Some _ func ()应该被调用,以便通知您数据位于。
document.domain
注意,这是一个 iframe 方法,它将 document.domain 的值设置为当前域的后缀。如果它这样做,较短的域将用于后续的原点检查。例如,假设文档中 http://store.company.com/dir/other.html处的脚本执行以下语句:
http://store.company.com/dir/other.html
document.domain = "company.com";
该语句执行后,页面将通过 http://company.com/dir/page.html的原点检查。然而,出于同样的原因,company.com 无法将 document.domain设置为 othercompany.com。
http://company.com/dir/page.html
othercompany.com
使用这种方法,您可以从来源于主域的页面上来源于子域的 iframe 执行 javascript。这种方法不适合跨域资源,因为像 Firefox 这样的浏览器不允许您将 document.domain更改为完全陌生的域。
资料来源: https://developer.mozilla.org/en/Same_origin_policy_for_JavaScript
跨来源资源共享 (CORS)是一个 W3C 工作草案,定义了浏览器和服务器在跨源访问源代码时必须如何通信。CORS 背后的基本思想是使用定制的 HTTP 头,使浏览器和服务器都能够充分了解对方,以确定请求或响应是成功还是失败。
对于一个简单的请求,一个使用 GET或 POST但没有自定义头并且其主体是 text/plain的请求,请求将与一个额外的称为 Origin的头一起发送。OriginHeader 包含请求页面的来源(协议、域名和端口) ,因此服务器可以轻松确定它是否应该提供响应。示例 Origin头文件可能如下所示:
GET
POST
text/plain
Origin
Origin: http://www.stackoverflow.com
如果服务器决定应该允许请求,它将发送一个 Access-Control-Allow-Origin头回显到发送的原点,如果是公共资源,则发送一个 *头回显。例如:
Access-Control-Allow-Origin
*
Access-Control-Allow-Origin: http://www.stackoverflow.com
如果这个标题丢失了,或者起源不匹配,那么浏览器将不允许请求。如果一切正常,那么浏览器将处理请求。请注意,请求和响应都不包括 cookie 信息。
Mozilla 团队在 他们关于 CORS 的帖子中建议,您应该检查是否存在 withCredentials属性,以确定浏览器是否通过 XHR 支持 CORS。然后,您可以结合 XDomainRequest对象的存在来覆盖所有浏览器:
withCredentials
XDomainRequest
function createCORSRequest(method, url){ var xhr = new XMLHttpRequest(); if ("withCredentials" in xhr){ xhr.open(method, url, true); } else if (typeof XDomainRequest != "undefined"){ xhr = new XDomainRequest(); xhr.open(method, url); } else { xhr = null; } return xhr; } var request = createCORSRequest("get", "http://www.stackoverflow.com/"); if (request){ request.onload = function() { // ... }; request.onreadystatechange = handler; request.send(); }
注意,要使 CORS 方法工作,您需要访问任何类型的服务器头机制,而不能简单地访问任何第三方资源。
资料来源: http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/
当调用 window.postMessage时,当任何必须执行的挂起的脚本完成时(例如,如果从事件处理程序调用 window.postMessage,那么剩余的事件处理程序,以前设置的挂起超时等等) ,目标窗口就会发送一个 MessageEvent。MessageEvent具有类型消息,data属性被设置为提供给 window.postMessage的第一个参数的字符串值,origin属性对应于在调用 window.postMessage时调用 window.postMessage的窗口中主文档的原点,以及 source属性,source属性是调用 window.postMessage的窗口。
MessageEvent
data
origin
source
要使用 window.postMessage,必须附加一个事件侦听器:
// Internet Explorer window.attachEvent('onmessage',receiveMessage); // Opera/Mozilla/Webkit window.addEventListener("message", receiveMessage, false);
而且必须声明一个 receiveMessage函数:
receiveMessage
function receiveMessage(event) { // do something with event.data; }
场外 iframe 还必须通过 postMessage正确发送事件:
postMessage
<script>window.parent.postMessage('foo','*')</script>
任何窗口都可以在任何其他窗口上随时访问此方法,无论文档在窗口中的位置如何,都可以向其发送消息。因此,用于接收消息的任何事件侦听器都必须首先使用原始属性和可能的源属性检查消息发送者的标识。这不能被低估: 如果不检查 ABC0和可能的 source属性,就会引发跨网站脚本攻击。
资料来源: https://developer.mozilla.org/en/DOM/window.postMessage
我想到了 JSONP:
JSONP 或“ JSONP”是一个 对基本 JSON 数据的补充 格式,这是一种使用模式,它允许 页请求和更有意义的 使用来自其他服务器的 JSON JSONP 是一个主服务器 替代最近的方法 叫做跨来源资源共享。
我在 PHP 中使用 curl 来规避这个问题,我在82端口运行了一个 webservice。
<?php $curl = curl_init(); $timeout = 30; $ret = ""; $url="http://localhost:82/put_val?val=".$_GET["val"]; curl_setopt ($curl, CURLOPT_URL, $url); curl_setopt ($curl, CURLOPT_FOLLOWLOCATION, 1); curl_setopt ($curl, CURLOPT_MAXREDIRS, 20); curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt ($curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5"); curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, $timeout); $text = curl_exec($curl); echo $text; ?>
下面是调用 PHP 文件的 javascript
function getdata(obj1, obj2) { var xmlhttp; if (window.XMLHttpRequest) xmlhttp=new XMLHttpRequest(); else xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4 && xmlhttp.status==200) { document.getElementById("txtHint").innerHTML=xmlhttp.responseText; } } xmlhttp.open("GET","phpURLFile.php?eqp="+obj1+"&val="+obj2,true); xmlhttp.send(); }
我的 HTML 在80端口的 WAMP 上运行,所以我们可以看到,同样的原始策略已经被规避了: -)
最近我发现的克服同源策略的方法是 http://anyorigin.com/
这个站点的设计使得你只需要给它任意的 url,它就会为你生成 javascript/jquery 代码,让你得到 html/data,而不管它的来源是什么。换句话说,它使任何 URL 或网页成为 JSONP 请求。
我发现它很有用:)
下面是一些来自任何来源的 javascript 代码示例:
$.getJSON('http://anyorigin.com/get?url=google.com&callback=?', function(data){ $('#output').html(data.contents); });
AnyOrigin 在一些 https 站点上运行不太好,所以我只是编写了一个名为 Whateverorigin.org的开源替代程序,它似乎在 https 上运行得很好。
Github 代码。