规避原产地政策的方法


150

同一原产地政策

我想制作有关HTML / JS 同源策略的社区Wiki,以希望能帮助任何人搜索此主题。这是关于SO的最热门搜索主题之一,并且没有统一的Wiki,所以我在这里:)

相同的来源策略可防止从一个来源加载的文档或脚本从另一个来源获取或设置文档的属性。该策略可追溯到Netscape Navigator 2.0。

您采用哪种最喜欢的方式处理同源政策?

请保持详细示例,并最好也链接您的资源。


4
不错的主意。您应该将示例放入答案中;就目前而言,这使问题变得相当庞大
Shog9 2010年

1
您还应该为每种方法添加安全隐患的列表。JSONP对于私有数据非常不安全。
艾伦(Erlend)

为什么要关闭?在过去的两年中,这个(维基)问题非常有用。此外,许多答案通过引用的支持。可以理解的是,not constructive标签似乎完全是荒谬的。投票要求重新开放。
David Titarenco,2012年

Answers:


84

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.domainothercompany.com

使用此方法,您可以从源于主域的页面上的子域的iframe中提取javascript。此方法不适用于跨域资源,因为Firefox之类的浏览器不允许您将更document.domain改为完全异类的域。

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

跨域资源共享方法

  • 方法类型:AJAX

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

对于一个简单的请求,该请求使用GETPOST不使用任何自定义标头,并且其主体为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从事件处理程序调用了剩余的事件处理程序,预先设置的待处理超时等),在目标窗口处调度a 。的MessageEvent具有类型消息,data其被设置为提供到所述第一参数的字符串值属性window.postMessage,一个origin对应于窗口调用主文档的原点属性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以下方式正确发送事件:

<script>window.parent.postMessage('foo','*')</script>

无论文档在窗口中的位置如何,任何窗口都可以随时在任何其他窗口上访问此方法,以向其发送消息。因此,用于接收消息的任何事件侦听器都必须首先使用原始属性和可能的​​源属性检查消息发送者的身份。这不能低估:无法检查origin和可能的source属性将启用跨站点脚本攻击。

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



我希望即时消息为时不晚:仅由一个问题是,本地主机始终是一个例外吗?总是不允许吗?我应该停止通过本地主机进行测试吗?
阿亚什(Ayyash)2012年

1
我不确定为什么,但是当我设置: Access-Control-Allow-Origin: http://www.stackoverflow.com/而不是:Access-Control-Allow-Origin: http://www.stackoverflow.com(URL末尾的斜杠)时,它在Safari和FF中不起作用,但在Chrome中起作用。当然,没有斜杠在所有浏览器中都可以正常工作。
mtfk 2012年

1
值得让人们知道该postMessage方法仅适用于支持该方法的浏览器,因为它是HTML5的补充。这个插件试图解决这个问题。刚提到它是因为我正在努力学习。
IronicMuffin 2012年

41

反向代理方法

  • 方法类型: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

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


17

我使用JSONP。

基本上,您添加

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

在您的页面上。

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


7
JSONP有两个问题:a)您正在向目标域添加脚本标签。他们可以发回任何东西,甚至是常规的javascript(XSS攻击)。因此,您真的必须信任他们不要做坏事或被黑b)任何其他网页都可以添加相同的脚本标签并窃取数据,因此永远不要将JSONP用于私有数据。
Erlend)

1
@Erlend:任何人都可以检索网络上提供的任何信息(除非需要正确的身份验证)。信息的确切格式不会使这种情况变得更好或更糟,即使是JSONP也是如此。
T-Bull'2

2
@ T-Bull:问题在于,JSONP无法进行正确的身份验证。用户登录站点A,然后转到站点B,站点B使用JSONP脚本标记从A加载数据。很好,也很好。然后,用户被诱骗访问邪恶站点C,该站点还使用JSONP脚本标记从A加载数据。因此,由于用户已通过A身份验证,因此C的所有者现在可以从A窃取用户数据。即使用户使用两因素身份验证对A进行身份验证。问题在于JSONP非常不安全。JSONP不是演示文稿。这是不安全的数据传输。
Erlend

1
JSONP仅支持HTTP GET。
鸦片2012年

这代表什么.js文件->“ http://..../ someData.js...。我正在尝试从另一个站点客户端读取dom,并且需要规避同源策略。
CS_2013

13

AnyOrigin在某些HTTPS站点上无法正常运行,因此我只写了一个开放源代码的替代品,无论它是什么,都可以与https很好地兼容。

代码在GitHub上


@DavidTitarenco-这让我发疯,试图了解Anyorigin腹部发生的某些事情。幸运的是,我发现了一篇博客文章对您有所帮助,现在,如果他需要,下一个家伙将拥有一个可以正常运行的测试站点。
ripper234

@neoascetic-修复了用法...现在需要对URL进行编码。
ripper234'3

12

克服我发现的同源策略的最新方法是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);
});

虽然它给了我一些问题与https网站,那么看看下面我的开源替代品:stackoverflow.com/questions/3076414/...
ripper234

13
这意味着:a)anyorigin能够读取通过tem传输的所有数据b)anyorigin可以对您的网站进行XSS,读取您站点上的所有数据,并将恶意软件交付给用户(如果anyorigin被黑客入侵会怎样?)
Erlend

@Erlend-分叉Whateverorigin并将其托管在您自己的服务器上。该代码是微不足道的,因此您可以对其进行检查,以确保没有任何漏洞隐藏在那里。
ripper234'3


3

JSONP想到:

JSONP或“带填充的JSON”是对基本JSON数据格式的补充,这种使用模式允许页面请求并更有意义地使用来自主服务器以外的服务器的JSON。JSONP是最新方法“跨域资源共享”的替代方法。


请参阅上面我对JSONP的评论。私人数据不是一个好选择。
Erlend)

1

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

还有一些流行的Javascript工具包的插件,它们window.postMessage使用上述其他方法提供了与旧版浏览器相似的功能。


1

好吧,我在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上运行。因此,我们绕过了相同的来源策略:-)



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.