规避同源策略的方法

发布于 2024-09-06 10:47:23 字数 306 浏览 17 评论 0原文

同源策略

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

同源策略可以防止 从其中加载的文档或脚本 起源于获取或设置 另一个文档的属性 起源。该政策自始至终 返回 Netscape Navigator 2.0。

您最喜欢的绕过同源策略的方法是什么?

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

The same origin policy

I wanted to make a community wiki regarding HTML/JS same-origin policies to hopefully help anyone searching for this topic. This is one of the most searched-for topics on SO and there is no consolidated wiki for it so here I go :)

The same origin policy prevents a
document or script loaded from one
origin from getting or setting
properties of a document from another
origin. This policy dates all the way
back to Netscape Navigator 2.0.

What are some of your favorite ways to go around same-origin policies?

Please keep examples verbose and preferably also link your sources.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

惟欲睡 2024-09-13 10:47:23

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 标头,让浏览器和服务器充分了解彼此,以确定请求或响应应该成功还是失败。

对于简单请求(使用 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 被调用时,会在任何必须执行的待处理脚本完成时(例如,如果 window .postMessage 从事件处理程序、先前设置的挂起超时等中调用。 MessageEvent 具有消息类型、一个 data 属性(设置为提供给 window.postMessage 的第一个参数的字符串值)、一个 < code>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 和可能的源属性来检查消息发送者的身份。这不能被低估:未能检查 origin 以及可能的 source 属性会导致跨站点脚本攻击。

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

The document.domain method

  • Method type: iframe.

Note that this is an iframe method that sets the value of document.domain to a suffix of the current domain. If it does so, the shorter domain is used for subsequent origin checks. For example, assume a script in the document at http://store.company.com/dir/other.html executes the following statement:

document.domain = "company.com";

After that statement executes, the page would pass the origin check with http://company.com/dir/page.html. However, by the same reasoning, company.com could not set document.domain to othercompany.com.

With this method, you would be allowed to exectue javascript from an iframe sourced on a subdomain on a page sourced on the main domain. This method is not suited for cross-domain resources as browsers like Firefox will not allow you to change the document.domain to a completely alien domain.

Source: https://developer.mozilla.org/en/Same_origin_policy_for_JavaScript

The Cross-Origin Resource Sharing method

  • Method type: AJAX.

Cross-Origin Resource Sharing (CORS) is a W3C Working Draft that defines how the browser and server must communicate when accessing sources across origins. The basic idea behind CORS is to use custom HTTP headers to allow both the browser and the server to know enough about each other to determine if the request or response should succeed or fail.

For a simple request, one that uses either GET or POST with no custom headers and whose body is text/plain, the request is sent with an extra header called Origin. The Origin header contains the origin (protocol, domain name, and port) of the requesting page so that the server can easily determine whether or not it should serve a response. An example Origin header might look like this:

Origin: http://www.stackoverflow.com

If the server decides that the request should be allowed, it sends a Access-Control-Allow-Origin header echoing back the same origin that was sent or * if it’s a public resource. For example:

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

If this header is missing, or the origins don’t match, then the browser disallows the request. If all is well, then the browser processes the request. Note that neither the requests nor responses include cookie information.

The Mozilla team suggests in their post about CORS that you should check for the existence of the withCredentials property to determine if the browser supports CORS via XHR. You can then couple with the existence of the XDomainRequest object to cover all browsers:

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();
}

Note that for the CORS method to work, you need to have access to any type of server header mechanic and can't simply access any third-party resource.

Source: http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/

The window.postMessage method

  • Method type: iframe.

window.postMessage, when called, causes a MessageEvent to be dispatched at the target window when any pending script that must be executed completes (e.g. remaining event handlers if window.postMessage is called from an event handler, previously-set pending timeouts, etc.). The MessageEvent has the type message, a data property which is set to the string value of the first argument provided to window.postMessage, an origin property corresponding to the origin of the main document in the window calling window.postMessage at the time window.postMessage was called, and a source property which is the window from which window.postMessage is called.

To use window.postMessage, an event listener must be attached:

    // Internet Explorer
    window.attachEvent('onmessage',receiveMessage);

    // Opera/Mozilla/Webkit
    window.addEventListener("message", receiveMessage, false);

And a receiveMessage function must be declared:

function receiveMessage(event)
{
    // do something with event.data;
}

The off-site iframe must also send events properly via postMessage:

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

Any window may access this method on any other window, at any time, regardless of the location of the document in the window, to send it a message. Consequently, any event listener used to receive messages must first check the identity of the sender of the message, using the origin and possibly source properties. This cannot be understated: Failure to check the origin and possibly source properties enables cross-site scripting attacks.

Source: https://developer.mozilla.org/en/DOM/window.postMessage

檐上三寸雪 2024-09-13 10:47:23

反向代理方法

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

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

The Reverse Proxy method

  • Method type: Ajax

Setting up a simple reverse proxy on the server, will allow the browser to use relative paths for the Ajax requests, while the server would be acting as a proxy to any remote location.

If using mod_proxy in Apache, the fundamental configuration directive to set up a reverse proxy is the ProxyPass. It is typically used as follows:

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

In this case, the browser would be able to request /ajax/web_service.xml as a relative URL, but the server would serve this by acting as a proxy to http://other-domain.com/ajax/web_service.xml.

One interesting feature of the this method is that the reverse proxy can easily distribute requests towards multiple back-ends, thus acting as a load balancer.

等待我真够勒 2024-09-13 10:47:23

我使用 JSONP。

基本上,您

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

在页面上添加。

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

I use JSONP.

Basically, you add

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

on your page.

some_func() should get called so that you are notified that the data is in.

ら栖息 2024-09-13 10:47:23

AnyOrigin 在某些 https 网站上运行不佳,所以我只是编写了一个名为 whateverorigin.org 的开源替代方案,它似乎可以工作与 https 配合良好。

github 上的代码

AnyOrigin didn't function well with some https sites, so I just wrote an open source alternative called whateverorigin.org that seems to work well with https.

Code on github.

此刻的回忆 2024-09-13 10:47:23

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

The most recent way of overcoming the same-origin policy that I've found is http://anyorigin.com/

The site's made so that you just give it any url and it generates javascript/jquery code for you that lets you get the html/data, regardless of it's origin. In other words, it makes any url or webpage a JSONP request.

I've found it pretty useful :)

Here's some example javascript code from anyorigin:

$.getJSON('http://anyorigin.com/get?url=google.com&callback=?', function(data){
    $('#output').html(data.contents);
});
倥絔 2024-09-13 10:47:23

我想到了 JSONP

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

The JSONP comes to mind:

JSONP or "JSON with padding" is a
complement to the base JSON data
format, a usage pattern that allows a
page to request and more meaningfully
use JSON from a server other than the
primary server. JSONP is an
alternative to a more recent method
called Cross-Origin Resource Sharing.

潦草背影 2024-09-13 10:47:23

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

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

Personally, window.postMessage is the most reliable way that I've found for modern browsers. You do have to do a slight bit more work to make sure you're not leaving yourself open to XSS attacks, but it's a reasonable tradeoff.

There are also several plugins for the popular Javascript toolkits out there that wrap window.postMessage that provide similar functionality to older browsers using the other methods discussed above.

月依秋水 2024-09-13 10:47:23

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

Well, I used curl in PHP to circumvent this. I have a webservice running in port 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;

?>

Here is the javascript that makes the call to the PHP file

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();
}

My HTML runs on WAMP in port 80. So there we go, same origin policy has been circumvented :-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文