150

同源政策

我想创建一个关于 HTML/JS同源策略的社区 wiki ,希望能帮助任何搜索这个主题的人。这是在 SO 上搜索最多的主题之一,并且没有统一的 wiki,所以我开始了 :)

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

您最喜欢的绕过同源策略的方式有哪些?

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

4

11 回答 11

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从事件处理程序调用剩余的事件处理程序,先前设置的挂起超时等),会导致在目标窗口调度。具有MessageEvent消息类型、data设置为提供给的第一个参数的字符串值的window.postMessage属性、与调用时origin调用的窗口中的主文档的来源相对应的属性,以及作为来自的窗口的属性这就是所谓的。window.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

于 2010-06-19T18:06:19.883 回答
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.

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

于 2010-06-19T17:07:02.417 回答
17

我使用 JSONP。

基本上,您添加

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

在您的页面上。

应该调用 some_func() 以便通知您数据在其中。

于 2010-06-19T17:09:09.530 回答
13

AnyOrigin 在某些 https 站点上运行不佳,因此我只是编写了一个名为whateverorigin.org的开源替代方案,它似乎与 https 一起工作得很好。

github 上的代码

于 2011-10-27T00:45:00.247 回答
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);
});
于 2011-05-24T00:03:46.980 回答
12

我不能声称这张图片的功劳,但它与我在这个主题上所知道的一切相匹配,同时也提供了一点幽默感。

http://www.flickr.com/photos/iluvrhinestones/5889370258/

于 2011-11-14T02:50:31.703 回答
3

想到JSONP

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

于 2010-06-19T19:07:37.363 回答
1

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

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

于 2010-06-19T17:06:01.827 回答
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 上运行。所以我们开始了,同源策略已被规避 :-)

于 2011-04-12T09:05:50.560 回答
1

以下是同源策略的一些解决方法和解释:
Thiru 的博客 - 浏览器同源策略解决方法

于 2011-12-12T16:37:18.440 回答
1

这几乎分析了那里可用的内容:http ://www.slideshare.net/SlexAxton/break-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

于 2012-04-19T23:56:22.260 回答