我想制作一个关于HTML / JS 同源策略的社区wiki,希望能帮助任何搜索此主题的人。这是关于SO的搜索次数最多的主题之一,并且没有统一的wiki,所以我在这里:)
相同的原始政策阻止了 从一个加载的文档或脚本 得到或设置的起源 另一个文档的属性 起源。这项政策始终贯彻始终 回到Netscape Navigator 2.0。
请保持示例详细,最好还链接您的来源。
答案 0 :(得分:84)
document.domain
方法请注意,这是一个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
Cross-Origin Resource Sharing(CORS)是W3C工作草案,它定义了浏览器和服务器在访问源文件时必须进行通信的方式。 CORS背后的基本思想是使用自定义HTTP标头,允许浏览器和服务器相互了解,以确定请求或响应是成功还是失败。
对于一个使用GET
或POST
且没有自定义标头且其正文为text/plain
的简单请求,请求将使用名为{{1}的额外标头发送}。 Origin标头包含请求页面的来源(协议,域名和端口),以便服务器可以轻松确定它是否应该提供响应。示例Origin
标头可能如下所示:
Origin
如果服务器决定应该允许该请求,它会发送一个Origin: http://www.stackoverflow.com
标头回显发送的相同来源,如果它是公共资源,则发送Access-Control-Allow-Origin
。例如:
*
如果缺少此标头,或者原点不匹配,则浏览器不允许该请求。如果一切顺利,则浏览器处理请求。请注意,请求和响应都不包含cookie信息。
Mozilla团队在their post about CORS建议您应检查是否存在Access-Control-Allow-Origin: http://www.stackoverflow.com
属性,以确定浏览器是否通过XHR支持CORS。然后,您可以结合withCredentials
对象的存在来覆盖所有浏览器:
XDomainRequest
请注意,要使CORS方法起作用,您需要访问任何类型的服务器标头机制,并且不能简单地访问任何第三方资源。
来源:http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/
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();
}
方法 window.postMessage
会导致在必须执行的任何挂起脚本完成时在目标窗口调度window.postMessage
(例如,如果从{1}}调用MessageEvent
,则会保留事件处理程序事件处理程序,先前设置的挂起超时等。 window.postMessage
具有类型消息,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
非现场iframe还必须通过function receiveMessage(event)
{
// do something with event.data;
}
正确发送事件:
postMessage
任何窗口都可以在任何其他窗口上随时访问此方法,无论窗口中文档的位置如何,都可以向其发送消息。因此,用于接收消息的任何事件侦听器必须首先使用origin和可能的source属性检查消息发送者的身份。这不容低估:未检查<script>window.parent.postMessage('foo','*')</script>
和可能的origin
属性会启用跨站点脚本攻击。
答案 1 :(得分:41)
在服务器上设置简单的reverse proxy将允许浏览器使用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
的代理来实现此目的。
此方法的一个有趣特性是反向代理可以轻松地将请求分配到多个后端,从而充当load balancer。
答案 2 :(得分:17)
我使用JSONP。
基本上,你添加
<script src="http://..../someData.js?callback=some_func"/>
在您的页面上。
应该调用some_func(),以便通知您数据所在。
答案 3 :(得分:13)
AnyOrigin在某些https网站上运行不正常,所以我写了一个名为whateverorigin.org的开源替代方案,似乎与https配合得很好。
答案 4 :(得分:12)
克服我发现的同源政策的最新方法是http://anyorigin.com/
该网站的制作只是为了给你任何网址,它会为你生成javascript / jquery代码,让你获得html /数据,无论它是什么来源。换句话说,它使任何网址或网页成为JSONP请求。
我发现它非常有用:)
以下是来自anyorigin的一些示例javascript代码:
$.getJSON('http://anyorigin.com/get?url=google.com&callback=?', function(data){
$('#output').html(data.contents);
});
答案 5 :(得分:12)
我不能声称这张图片,但它与我在这个主题上所知道的一切相符,并且同时提供了一些幽默。
答案 6 :(得分:3)
JSONP浮现在脑海中:
JSONP或“带填充的JSON”是一个 补充基本JSON数据 格式,允许使用的使用模式 要求的页面,更有意义 从服务器以外的服务器使用JSON 主服务器。 JSONP是一个 替代更新的方法 称为跨源资源共享。
答案 7 :(得分:1)
就个人而言,window.postMessage
是我在现代浏览器中找到的最可靠的方式。你必须做更多的工作,以确保你不会让自己对XSS攻击开放,但这是一个合理的权衡。
还有一些流行的Javascript工具包的插件,其中包含window.postMessage
,使用上面讨论的其他方法提供与旧浏览器类似的功能。
答案 8 :(得分: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上运行。所以我们去了,同样的原始政策已被规避: - )
答案 9 :(得分:1)
以下是同源政策的一些解决方法和解释:
Thiru's Blog - Browser same origin policy workaround
答案 10 :(得分:1)