规避同源政策的方法

2022-08-30 03:02:22

同源策略

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

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

您最喜欢采用哪些方式来实施同源策略?

请保持示例冗长,最好也链接您的来源。


答案 1

方法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执行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,当调用时,当必须执行的任何挂起脚本完成时,将导致在目标窗口调度 (例如,如果从事件处理程序调用,则为剩余的事件处理程序,先前设置的挂起超时等)。具有类型消息,一个属性设置为提供给的第一个参数的字符串值,一个对应于调用时调用的窗口中主文档原点的属性,以及一个属性,该属性是从中调用的窗口。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>

任何窗口都可以随时在任何其他窗口上访问此方法,而不管文档在窗口中的位置如何,以向其发送消息。因此,用于接收消息的任何事件侦听器都必须首先使用源属性和可能的源属性来检查消息发送方的身份。这一点不容小觑:如果无法检查属性和可能的属性,则会导致跨站点脚本攻击。

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


答案 2

反向代理方法

  • 方法类型:阿贾克斯

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

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

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

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

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