规避同源策略的方法

Ways to circumvent the same-origin policy

提问人: 提问时间:6/20/2010 最后编辑:3 revs, 2 users 100%David Titarenco 更新时间:5/15/2014 访问量:740881

问:

已锁定。这个问题及其答案被锁定,因为这个问题偏离了主题,但具有历史意义。它目前不接受新的答案或交互。

同源策略

我想做一个关于HTML/JS同源政策的社区维基,希望能帮助任何搜索这个主题的人。这是 SO 上搜索次数最多的主题之一,并且没有针对它的合并 wiki,所以我在这里:)

同源策略可防止 从一个加载的文档或脚本 源自获取或设置 来自另一个文档的文档的属性 起源。这项政策一直追溯到 返回到 Netscape Navigator 2.0。

您最喜欢采用哪些方法来绕过同源策略?

请保持示例详细,最好还链接您的来源。

JavaScript ajax 同源策略

评论

4赞 Shog9 6/20/2010
好主意..不过,你应该把你的例子放在答案中;就目前而言,它们使问题变得相当庞大
1赞 Erlend 11/11/2011
您还应该为每种方法添加安全隐患列表。JSONP 对于私人数据非常不安全。
0赞 David Titarenco 8/15/2012
为什么收盘?在过去的 2 年里,这个 (wiki) 问题非常有用。此外,许多答案都有参考文献支持。解释将不胜感激,因为标签似乎完全是愚蠢的。投票赞成重新开放。not constructive

答:

1赞 Justin Niessner #1

就我个人而言,这是我为现代浏览器找到的最可靠的方法。你确实需要做更多的工作来确保你不会让自己受到XSS攻击,但这是一个合理的权衡。window.postMessage

还有一些流行的 Javascript 工具包的插件,这些插件使用上面讨论的其他方法提供与旧浏览器类似的功能。window.postMessage

41赞 4 revsDaniel Vassallo #2

反向代理方法

  • 方法类型:Ajax

在服务器上设置一个简单的反向代理,将允许浏览器对 Ajax 请求使用相对路径,而服务器将充当任何远程位置的代理。

如果在 Apache 中使用 mod_proxy,则设置反向代理的基本配置指令是 .它通常按如下方式使用:ProxyPass

ProxyPass     /ajax/     http://other-domain.com/ajax/

在这种情况下,浏览器将能够请求作为相对 URL,但服务器将通过充当 的代理来提供此请求。/ajax/web_service.xmlhttp://other-domain.com/ajax/web_service.xml

此方法的一个有趣功能是,反向代理可以轻松地将请求分发到多个后端,从而充当负载均衡器

17赞 Nicolas Viennot #3

我使用 JSONP。

基本上,你添加

<script src="http://..../someData.js?callback=some_func"/>

在您的页面上。

应调用 some_func(),以便通知您数据已进入。

评论

7赞 Erlend 11/11/2011
JSONP 有两个问题:a) 您正在向目标域添加脚本标记。他们可以发回任何东西,甚至是常规的javascript(XSS攻击)。所以你真的必须相信他们不会做坏事或被黑客入侵 b) 任何其他网页都可以添加相同的脚本标签,并窃取数据,所以永远不要将 JSONP 用于私人数据。
1赞 T-Bull 2/2/2012
@Erlend:任何人都可以检索网络上提供的任何信息(除非需要适当的身份验证)。该信息呈现方式的确切格式不会使它变得更好或更糟,即使它是 JSONP。
2赞 Erlend 2/4/2012
@T-Bull:问题在于,使用 JSONP 无法进行正确的身份验证。用户在站点 A 上登录,然后转到站点 B,该站点使用 JSONP 脚本标记从 A 加载数据。一如既往。然后用户被诱骗访问恶意站点 C,该站点也使用 JSONP 脚本标签从 A 加载数据。因此,由于用户已通过 A 身份验证,因此 C 的所有者现在可以从 A 窃取用户数据。即使用户使用双因素身份验证来向 A 进行身份验证也是如此。问题在于 JSONP 非常不安全。JSONP不是演示。这是不安全的数据传输。
1赞 opyate 4/1/2012
JSONP 仅支持 HTTP GET。
0赞 CS_2013 5/22/2012
这代表什么.js文件 -> “http://..../someData.js....我正在尝试从另一个站点客户端读取 dom,并且需要规避同源策略。
84赞 3 revs, 3 users 98%David Titarenco #4

方法document.domain

  • 方法类型:iframe

请注意,这是一个 iframe 方法,它将 document.domain 的值设置为当前域的后缀。如果这样做,则较短的域将用于后续的源检查。例如,假设文档 at 中的脚本执行以下语句:http://store.company.com/dir/other.html

document.domain = "company.com";

执行该语句后,页面将使用 .但是,出于同样的原因,company.com 无法设置为 。http://company.com/dir/page.htmldocument.domainothercompany.com

使用此方法,您将被允许从源自子域的 iframe 执行源自 main 域的页面上的 javascript。此方法不适合跨域资源,因为像Firefox这样的浏览器不允许您将域更改为完全陌生的域。document.domain

来源:https://developer.mozilla.org/en/Same_origin_policy_for_JavaScript

跨域资源共享方法

  • 方法类型:AJAX

跨域资源共享 (CORS) 是 W3C 工作草案,它定义了浏览器和服务器在跨源访问源时必须如何通信。CORS 背后的基本思想是使用自定义 HTTP 标头,使浏览器和服务器能够充分了解彼此,以确定请求或响应是成功还是失败。

对于简单请求,该请求使用或不使用自定义标头,并且其正文为 ,该请求将使用一个名为 的额外标头发送。Origin 标头包含请求页面的来源(协议、域名和端口),以便服务器可以轻松确定是否应提供响应。示例标头可能如下所示:GETPOSTtext/plainOriginOrigin

Origin: http://www.stackoverflow.com

如果服务器决定应允许该请求,则它会发送一个标头,回显发送的同一源,或者如果它是公共资源。例如:Access-Control-Allow-Origin*

Access-Control-Allow-Origin: http://www.stackoverflow.com

如果缺少此标头,或者源不匹配,则浏览器将禁止该请求。如果一切正常,则浏览器将处理请求。请注意,请求和响应均不包含 cookie 信息。

Mozilla团队在他们关于CORS的帖子中建议,你应该检查该属性是否存在,以确定浏览器是否通过XHR支持CORS。然后,您可以结合对象的存在来覆盖所有浏览器:withCredentialsXDomainRequest

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,调用时,当任何必须执行的挂起脚本完成时,将导致在目标窗口调度 a(例如,如果从事件处理程序调用,则剩余的事件处理程序、先前设置的挂起超时等)。具有 message 类型、设置为提供给的第一个参数的字符串值的属性、与调用时调用的窗口中主文档的来源相对应的属性,以及作为调用窗口的属性。MessageEventwindow.postMessageMessageEventdatawindow.postMessageoriginwindow.postMessagewindow.postMessagesourcewindow.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 属性检查消息发送方的身份。这一点不容小觑:未能检查源和可能的属性会导致跨站点脚本攻击。

来源:https://developer.mozilla.org/en/DOM/window.postMessage

评论

0赞 Ayyash 3/13/2012
我希望我得到答案还为时不晚:唯一的问题是,localhost 总是一个例外吗?总是不允许吗?我应该停止通过我的本地主机进行测试吗?
1赞 mtfk 5/21/2012
我不确定为什么,但是当我设置:而不是:(url末尾的斜杠)时,它在Safari和FF中不起作用,但在Chrome中起作用。当然,没有斜杠在所有浏览器中都可以正常工作。Access-Control-Allow-Origin: http://www.stackoverflow.com/Access-Control-Allow-Origin: http://www.stackoverflow.com
1赞 IronicMuffin 8/3/2012
可能值得让人们知道该方法仅适用于支持它的浏览器,因为它是 HTML5 的添加。这个插件试图解释这一点。只是提到它,因为我正在以艰难的方式学习这个。postMessage
3赞 Sarfraz #5

我想到了 JSONP

JSONP 或“带填充的 JSON”是一个 对基本 JSON 数据的补充 format,一种允许 页面请求和更有意义的 使用来自服务器的 JSON 主服务器。JSONP 是一个 较新方法的替代方法 称为跨域资源共享。

评论

0赞 Erlend 11/11/2011
请参阅我上面对 JSONP 的评论。对于私人数据来说,这不是一个好的选择。
1赞 harihb #6

好吧,我在 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 在端口 80 的 WAMP 上运行。所以我们开始了,同源政策已被规避:-)

12赞 2 revsrk1s #7

我发现克服同源策略的最新方法是 http://anyorigin.com/

该网站的制作使您只需给它任何 url,它就会为您生成 javascript/jquery 代码,让您获取 html/data,无论它的来源如何。换句话说,它使任何 url 或网页成为 JSONP 请求。

我发现它非常有用:)

以下是来自 anyorigin 的一些示例 javascript 代码:

$.getJSON('http://anyorigin.com/get?url=google.com&callback=?', function(data){
    $('#output').html(data.contents);
});

评论

0赞 ripper234 10/27/2011
虽然它给我带来了一些 https 站点的问题,所以在下面查看我的开源替代方案:stackoverflow.com/questions/3076414/......
13赞 Erlend 11/11/2011
这意味着:a) anyorigin 将能够读取您通过 tem 传输的所有数据 b) anyorigin 可以对您的网站进行 XSS,读取您网站上的所有数据,并将恶意软件发送给您的用户(如果 anyorigin 被黑客入侵会怎样?
0赞 ripper234 3/19/2012
@Erlend - 分叉 Whateverorigin 并将其托管在您自己的服务器上。代码是微不足道的,因此您可以对其进行检查以确保那里没有隐藏任何漏洞。
13赞 ripper234 #8

AnyOrigin 在某些 https 站点上运行不佳,所以我只是编写了一个名为 whateverorigin.org 的开源替代方案,它似乎适用于 https。

github 上的代码

评论

0赞 ripper234 10/27/2011
@DavidTitarenco - 它让我发疯,试图了解 Anyorigin 肚子里发生的一些事情。幸运的是,我找到了一篇有帮助的博客文章,现在下一个人将有一个工作测试站点,如果他需要的话。
0赞 ripper234 3/19/2012
@neoascetic - 修复了用法...现在需要对 URL 进行编码。