规避同源策略的方法
- 2024-11-02 21:00:00
- admin 原创
- 36
问题描述:
同源策略
我想创建一个关于 HTML/JS同源策略的社区 wiki ,希望能帮助到任何搜索此主题的人。这是 SO 上搜索最多的主题之一,但目前还没有统一的 wiki,所以我就来写这个吧 :)
同源策略可防止从一个源加载的文档或脚本获取或设置来自另一个源的文档的属性。此策略可追溯到 Netscape Navigator 2.0。
您最喜欢用什么方法来绕过同源策略?
请保持示例的详细程度并且最好还链接您的来源。
解决方案 1:
方法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 的文章中建议,你应该检查该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.postMessagesource
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
:
<script>window.parent.postMessage('foo','*')</script>
任何窗口都可以随时在任何其他窗口上访问此方法,无论文档在窗口中的位置如何,都可以向其发送消息。因此,用于接收消息的任何事件侦听器都必须首先使用 origin 和可能的 source 属性检查消息发送者的身份。这一点不容低估:未能检查origin
和可能的source
属性会导致跨站点脚本攻击。
来源:https://developer.mozilla.org/en/DOM/window.postMessage
解决方案 2:
反向代理方法
方法类型: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
。
该方法的一个有趣特性是反向代理可以轻松地将请求分发到多个后端,从而充当负载均衡器。
解决方案 3:
我使用 JSONP。
基本上,你添加
<script src="http://..../someData.js?callback=some_func"/>
在您的页面上。
应该调用 some_func(),以便通知您数据已输入。
解决方案 4:
AnyOrigin 在某些 https 站点上运行不佳,因此我刚刚编写了一个名为whateverorigin.org的开源替代方案,它似乎可以很好地与 https 配合使用。
代码在 github 上。
解决方案 5:
我发现的最新克服同源策略的方法是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);
});
解决方案 6:
我想到的是JSONP:
JSONP 或“带填充的 JSON”是对基本 JSON 数据格式的补充,这种使用模式允许页面从主服务器以外的服务器请求并更有意义地使用 JSON。JSONP 是一种称为跨源资源共享的较新方法的替代方案。
解决方案 7:
就我个人而言,window.postMessage
这是我发现的适用于现代浏览器的最可靠方法。您确实需要做更多工作来确保您不会受到 XSS 攻击,但这是一个合理的权衡。
还有几种流行的 Javascript 工具包的插件,它们可以window.postMessage
使用上面讨论的其他方法为旧版浏览器提供类似的功能。
解决方案 8:
好吧,我使用 PHP 中的 curl 来解决这个问题。我在端口 82 上运行了一个 Web 服务。
<?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 在 WAMP 的 80 端口上运行。这样一来,同源策略就被规避了 :-)
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件