如何规避同源政策
同源政策
我想制作一个关于HTML / JS 同源政策的社区维基,希望能帮助任何人搜索这个主题。 这是SO上搜索次数最多的主题之一,没有统一的wiki,所以我去:)
相同的源策略可防止从一个源加载的文档或脚本从另一个源获取或设置文档的属性。 此政策可以追溯到Netscape Navigator 2.0。
您最喜欢采用同源政策的方式有哪些?
请保持示例详细,最好还链接您的来源。
document.domain
方法
- 方法类型: iframe 。
请注意,这是一个iframe方法,它将document.domain的值设置为当前域的后缀。 如果这样做,则较短的域用于后续的原始检查。 例如,假设文档http://store.company.com/dir/other.html
的脚本执行以下语句:
document.domain = "company.com";
执行该语句后,该页面将通过http://company.com/dir/page.html
传递原始检查。 但是,由于同样的原因,company.com无法将document.domain
设置为othercompany.com
。
使用此方法,您将被允许从源自主域上的页面上的子域的iframe中提取javascript。 此方法不适用于跨域资源,因为Firefox等浏览器不允许您将document.domain
更改为完全异类域。
资料来源: https : //developer.mozilla.org/en/Same_origin_policy_for_JavaScript
跨源资源共享方法
- 方法类型: AJAX 。
跨源资源共享 (CORS)是W3C工作草案,它定义了在访问源的源时浏览器和服务器必须如何通信。 CORS背后的基本思想是使用自定义HTTP标头,允许浏览器和服务器相互了解,以确定请求或响应是成功还是失败。
对于一个简单的请求,一个使用GET
或POST
而没有自定义标头且其主体为text/plain
的请求,该请求将使用名为Origin
的额外标头发送。 Origin标头包含请求页面的来源(协议,域名和端口),以便服务器可以轻松确定它是否应该提供响应。 示例Origin
标头可能如下所示:
Origin: http://www.stackoverflow.com
如果服务器决定应该允许该请求,它会发送一个Access-Control-Allow-Origin
标头,回显发送的相同源或*
如果它是公共资源。 例如:
Access-Control-Allow-Origin: http://www.stackoverflow.com
如果缺少此标头,或者原点不匹配,则浏览器不允许该请求。 如果一切顺利,则浏览器处理请求。 请注意,请求和响应都不包含cookie信息。
Mozilla团队在他们关于CORS的post中建议您应该检查withCredentials
属性的存在,以确定浏览器是否通过XHR支持CORS。 然后,您可以结合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
方法
- 方法类型: iframe 。
window.postMessage
在被调用时会导致在任何必须执行的挂起脚本完成时在目标窗口调度MessageEvent
(例如,如果从事件处理程序调用window.postMessage
,之前设置的挂起超时等,则保留事件处理程序。 )。 MessageEvent
具有类型消息,一个data
属性,设置为提供给window.postMessage
的第一个参数的字符串值,一个origin
属性,对应于窗口中窗口调用window.postMessage
的主文档的原点window.postMessage
调用了window.postMessage
并调用了一个source
属性,该属性是调用window.postMessage
的窗口。
要使用window.postMessage
,必须附加事件侦听器:
// Internet Explorer window.attachEvent('onmessage',receiveMessage); // Opera/Mozilla/Webkit window.addEventListener("message", receiveMessage, false);
并且必须声明receiveMessage
函数:
function receiveMessage(event) { // do something with event.data; }
场外iframe还必须通过postMessage
正确发送事件:
任何窗口都可以在任何其他窗口上随时访问此方法,无论窗口中文档的位置如何,都可以向其发送消息。 因此,用于接收消息的任何事件侦听器必须首先使用origin和可能的source属性检查消息发送者的身份。 这不能低估: 未检查origin
和可能的source
属性会导致跨站点脚本攻击。
资料来源: https : //developer.mozilla.org/en/DOM/window.postMessage
反向代理方法
- 方法类型: Ajax
在服务器上设置简单的反向代理将允许浏览器使用Ajax请求的相对路径,而服务器将充当任何远程位置的代理。
如果在Apache中使用mod_proxy ,则设置反向代理的基本配置指令是ProxyPass
。 它通常使用如下:
ProxyPass /ajax/ http://other-domain.com/ajax/
在这种情况下,浏览器可以将/ajax/web_service.xml
请求作为相对URL,但服务器将通过充当http://other-domain.com/ajax/web_service.xml
的代理来提供此服务。
该方法的一个有趣特征是反向代理可以轻松地将请求分配给多个后端,从而充当负载平衡器 。
我使用JSONP。
基本上,你添加
在你的页面上。
应该调用some_func(),以便通知您数据所在。
AnyOrigin在某些https网站上运行不正常,所以我刚刚编写了一个名为whateverorigin.org的开源替代方案,似乎与https配合得很好。
github上的代码 。
克服我发现的同源策略的最新方法是http://anyorigin.com/
该网站的制作只是为了给你任何url,它为你生成javascript / jquery代码,让你获得html /数据,无论它是什么来源。 换句话说,它使任何url或网页成为JSONP请求。
我发现它非常有用:)
以下是来自anyorigin的一些示例javascript代码:
$.getJSON('http://anyorigin.com/get?url=google.com&callback=?', function(data){ $('#output').html(data.contents); });
我不能声称这张图片,但它与我在这个主题上所知道的一切相符,同时也提供了一些幽默。
想到JSONP :
JSONP或“带填充的JSON”是对基本JSON数据格式的补充,这是一种允许页面请求并且更有意义地使用来自主服务器以外的服务器的JSON的使用模式。 JSONP是一种称为跨源资源共享的更新方法的替代方法。
就个人而言, window.postMessage
是我在现代浏览器中找到的最可靠的方式。 你必须做更多的工作,以确保你不会让自己对XSS攻击开放,但这是一个合理的权衡。
流行的Javascript工具包还有几个插件,它们包含window.postMessage
,它使用上面讨论的其他方法提供与旧浏览器类似的function。
好吧,我在PHP中使用curl来规避这个问题。 我有一个在端口82运行的web服务。
这是调用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上运行。所以我们去了,同样的原始策略已被规避:-)
以下是同源政策的一些解决方法和解释:
Thiru的博客 – 浏览器同源策略解决方法
这分析了几乎可用的内容: http : //www.slideshare.net/SlexAxton/breaking-the-cross-domain-barrier
对于postMessage解决方案,请查看:
https://github.com/chrissrogers/jquery-postmessage/blob/master/jquery.ba-postmessage.js
和略有不同的版本:
https://github.com/thomassturm/ender-postmessage/blob/master/ender-postmessage.js