如何规避同源政策
相同的来源政策
我想制作一个关于HTML / JS 同源策略的社区wiki,希望能帮助任何人search这个主题。 这是SO上search最多的主题之一,没有合并的wiki,所以在这里我去:)
相同的来源策略可防止从一个来源加载的文档或脚本从另一个来源获取或设置文档的属性。 这个政策可以追溯到Netscape Navigator 2.0。
什么是你最喜欢的方式来绕过同源政策?
请保持详细的例子,最好也链接你的来源。
document.domain
方法
- 方法types: 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
跨源资源共享方法
- 方法types: 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团队在他们的post中build议您应该检查是否存在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方法起作用,您需要访问任何types的服务器标题机制,并且不能简单地访问任何第三方资源。
资料来源: http : //www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/
window.postMessage
方法
- 方法types: iframe 。
调用window.postMessage
时,会在必须执行的任何挂起的脚本完成时(例如,如果从事件处理程序调用window.postMessage
,之前设置的挂起超时等,则剩余的事件处理程序),导致在目标窗口上分派MessageEvent
。 )。 MessageEvent
具有types消息,其data
属性被设置为提供给window.postMessage
的第一个参数的string值,该属性对应于在时间window.postMessage
调用window.postMessage
的窗口中主文档的来源window.postMessage
被调用的window.postMessage
,以及一个来自window.postMessage
被调用的窗口的source
属性。
要使用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
正确发送事件:
<script>window.parent.postMessage('foo','*')</script>
任何窗口都可以在任何其他窗口上随时访问此方法,无论文档在窗口中的位置如何,都可以向其发送消息。 因此,任何用于接收消息的事件侦听器都必须首先使用origin和可能的source属性来检查消息发送者的身份。 这不能被低估: 未能检查origin
和可能的source
属性会导致跨站点脚本攻击。
来源: https : //developer.mozilla.org/en/DOM/window.postMessage
反向代理方法
- 方法types: Ajax
在服务器上设置一个简单的反向代理 ,将允许浏览器为Ajax请求使用相对path,而服务器将作为任何远程位置的代理。
如果在Apache中使用mod_proxy ,则设置反向代理的基本configuration指令是ProxyPass
。 通常使用如下:
ProxyPass /ajax/ http://other-domain.com/ajax/
在这种情况下,浏览器将能够请求/ajax/web_service.xml
作为相对URL,但是服务器将通过作为http://other-domain.com/ajax/web_service.xml
的代理服务器。
这种方法的一个有趣的特点是反向代理可以轻松地将请求分发到多个后端,从而充当负载均衡器 。
我使用JSONP。
基本上,你添加
<script src="http://..../someData.js?callback=some_func"/>
在你的页面上。
some_func()应该被调用,以便通知你数据在。
AnyOrigin在某些https站点上运行不正常,所以我只写了一个名为whateverorigin.org的开源替代scheme,它似乎可以很好地与https协同工作。
在github上的代码 。
克服我发现的同源政策的最新方法是http://anyorigin.com/
该网站的制作,让你只要给它的任何url,它会为你生成javascript / jquery代码,让你得到的HTML /数据,不pipe它的起源。 换句话说,它使任何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
是我为现代浏览器find的最可靠的方法。 你必须做更多的工作来确保你不打开XSS攻击,但这是一个合理的折衷。
还有一些stream行的Javascript工具箱的插件,它们包装了window.postMessage
,它使用上面讨论的其他方法为旧版浏览器提供了类似的function。
那么,我在PHP中使用curl来规避这一点。 我有一个web服务在端口82运行。
<?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。所以我们去,同样的起源政策已经绕过:-)
以下是同源策略的一些解决方法和解释:
Thiru的博客 – 浏览器相同的来源政策解决方法
这几乎分析了什么是可用的: http : //www.slideshare.net/SlexAxton/breaking-the-cross-domain-barrier
对于postMessage解决scheme,请看看:
chrissrogers/jquery-postmessage/blob/master/jquery.ba-postmessage.html
和一个稍微不同的版本:
https://github.com/thomassturm/ender-postmessage/blob/master/ender-postmessage.js