Cross-Domain 跨域

1. 使用 jsonp 跨域

http://www.ibm.com/developerworks/cn/web/wa-aj-jsonp1/

同源策略阻止从一个域上加载的脚本获取或操作另一个域上的文档属性。也就是说,受到请求的 URL 的域必须与当前 Web 页面的域相同。这意味着浏览器隔离来自不同源的内容,以防止它们之间的操作。这个浏览器策略很旧,从 Netscape Navigator 2.0 版本开始就存在。

克服该限制的一个相对简单的方法是让 Web 页面向它源自的 Web 服务器请求数据,并且让 Web 服务器像代理一样将请求转发给真正的第三方服务器。尽管该技术获得了普遍使用,但它是不可伸缩的。另一种方式是使用框架要素在当前 Web 页面中创建新区域,并且使用 GET 请求获取任何第三方资源。不过,获取资源后,框架中的内容会受到同源策略的限制。

克服该限制更理想方法是在 Web 页面中插入动态脚本元素,该页面源指向其他域中的服务 URL 并且在自身脚本中获取数据。脚本加载时它开始执行。该方法是可行的,因为同源策略不阻止动态脚本插入,并且将脚本看作是从提供 Web 页面的域上加载的。但如果该脚本尝试从另一个域上加载文档,就不会成功。幸运的是,通过添加 JavaScript Object Notation (JSON) 可以改进该技术。

首先设置 hosts 文件为(下同):

127.0.0.1 www.c.com
127.0.0.1 www.d.com

http://www.d.com/cd/demo.html :

<script type="text/javascript">
$(document).ready(function(){
    // use jquery
    $("#jsonp").click(function(){
        $.getJSON("http://www.c.com/cd/data-jsonp.php?callback=?",
        function(response){
            if(response){
                alert('output: a: ' + response.a + ', b: ' + response.b);
            } else {
                alert('error');
            }
        });
    });
 
    // dynamic create script
    $("#jsonp-append").click(function(){
        appendScript('http://www.c.com/cd/data-jsonp.php?callback=callbackFunc');
    });
});
 
// jsonp callback function
function callbackFunc(response) {
    if(response){
        alert('output: a: ' + response.a + ', b: ' + response.b);
    } else {
        alert('error');
    }
}
 
// dynamic create script
function appendScript(src) {
    //creat script
    var head = document.getElementsByTagName("head")[0];
    var script = document.createElement("script");
    script.setAttribute("src", src);
    script.setAttribute("type", "text/javascript");
    script.charset = "utf-8";
 
    // after script loaded, we remove the script
    script.onload = script.onreadystatechange = function(){
        if (!this.readyState || this.readyState == "loaded" ||
            this.readyState == "complete") {
            setTimeout(function(){
                head.removeChild(script);
            }, 50);
        }
    };
 
    // insert script
    head.appendChild(script);
}
</script>
<a href="#" id="jsonp">获取数据(jquery)</a>
<a href="#" id="jsonp-append">获取数据</a>

http://www.c.com/cd/data-jsonp.php :

$callback = isset($_GET['callback']) ? $_GET['callback'] : '';
echo "{$callback}(" . json_encode(array('a' => 1, 'b' => 2)) . ")";

2. 使用 flash & crossdomain.xml 跨域

http://blog.monstuff.com/archives/000280.html

http://www.d.com/cd/demo.html :

<script type="text/javascript" src="FlashHelper.js"></script>
<script type="text/javascript">
$(document).ready(function(){
    // flash & crossdomain.xml crossdomain
    $("#flash").click(function(){
        flashCall();
    });
});
 
// flash & crossdomain.xml crossdomain
function flashCallback() {
    var response = FlashHelper.getFlash().GetVariable("retText");
    // convert to json object
    response = eval("("+response+")");
    alert('output: a: ' + response.a + ', b: ' + response.b);
}
 
function flashCall() {
    var url = 'http://www.c.com/cd/data.php';
    var method = 'get';
    var body = '';
    var contentType = 'application/x-www-form-urlencoded';
 
    var fs = FlashHelper.getFlash();
    fs.XmlHttp(url, "flashCallback", method, body, contentType);
}
</script>
<a href="#" id="flash">获取数据</a>
 
<script type="text/javascript">
// flash & crossdomain.xml crossdomain
FlashHelper.writeFlash();
</script>

http://www.c.com/cd/data.php :

echo json_encode(array('a' => 1, 'b' => 2));

http://www.c.com/crossdomain.xml :

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
    <allow-access-from domain="*.c.com"/> 
    <allow-access-from domain="*.d.com"/> 
</cross-domain-policy>

3. 使用 iframe & url location hash 跨域

http://ued.alimama.com/?p=197

  • 父窗口通过改变子窗口的src中的hash值把一部分信息传入,如果src只有hash部分改变,那么子窗口是不会重新载入的。
  • 子窗口可以重写父窗口的location.href,但是注意这里子窗口无法读取而只能重写location.href所以要求前提是您控制两个域名,知道当前父窗口的location.href是什么并写在子窗口内,这样通过parent.location.href = "已知的父窗口的href"+"#"+hash。这样父窗口只有hash改变也不会重载。

http://www.d.com/cd/demo.html :

<script type="text/javascript">
$(document).ready(function(){
// iframe cross domain by location.hash
    $("#clientform").submit(function(){
        $("#serverframe").attr('src', 'http://www.c.com/cd/iframe-a.html?'
                               + Math.floor(Math.random() * 10000) + '#'
                               + $("#bgcolor").val());
        return false;
    });
 
 
});
</script>
<form id="clientform">
设置 iframe 的背景色: <br />
<select id="bgcolor">
    <option value="" selected>选择颜色</option>
    <option value="white">白色</option>
    <option value="black">黑色</option>
    <option value="red">红色</option>
    <option value="green">绿色</option>
    <option value="blue">蓝色</option>
</select>
<button type="submit" id="changecolor">Go!</button>
</form>
<iframe id="serverframe" width="210" height="150" frameborder="1" src="http://www.c.com/cd/iframe-a.html#white"></iframe>

http://www.c.com/cd/iframe-a.html :

<form id="serverform">
设置父页面的背景色: <br />
<select id="pbgcolor">
    <option value="" selected>选择颜色</option>
    <option value="white">白色</option>
    <option value="black">黑色</option>
    <option value="red">红色</option>
    <option value="green">绿色</option>
    <option value="blue">蓝色</option>
</select>
<button type="submit" id="pchangecolor">Go!</button>
</form>
<iframe id="iframe-agent" height="0" width="0" src="http://www.d.com/cd/iframe-agent.html" style="display:none"></iframe>
 
<script type="text/javascript">
var hashVal = window.location.hash.substr(1);
document.body.style.backgroundColor = hashVal;
 
// iframe cross domain by location.hash
$("#serverform").submit(function(){
    var iframeagent = document.getElementById("iframe-agent");
    iframeagent.src = iframeagent.src.split('#')[0] + "?"
                    + Math.floor(Math.random() * 10000) +"#" + $("#pbgcolor").val();
    return false;
});
</script>

http://www.d.com/cd/iframe-agent.html :

<script type="text/javascript">
var hash_color = window.location.hash.substr(1);
//var parentw = window.parent.parent.document.getElementById("cd-iframe");
//parentw.style.backgroundColor = hash_color;
window.parent.parent.document.body.style.backgroundColor = hash_color;
</script>

4. 各子域之间的 iframe 跨域

http://blog.csdn.net/lenel/archive/2007/10/24/1841483.aspx

如 bbs.xxx.com 的页面用 iframe 嵌入到 www.xxx.com 中, 一级域名都是 xxx.com
在父窗口和iframe内部分别加上: document.domain="xxx.com";
之后2个页面就等于在同一域名下,通过window.parent oIframe.contentDocument就可以相互访问,进行无障碍的JS通信

5. 使用 P3P 跨域设置cookie

http://hi.baidu.com/thinkinginlamp/blog/item/5e2a02084f1dafd163d9865f.html

http://www.d.com/cd/setcookie.php :

echo '<script src="http://www.c.com/cd/data-cookie.php?id=www.d.com"></script>';

http://www.c.com/cd/data-cookie.php :

header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
$cookie = !empty($_GET['id']) ? $_GET['id'] : 'none';
setcookie("cd-p3p", $cookie, time() + 3600, "/", ".c.com");

访问 http://www.d.com/cd/setcookie.php , 这时候可以看到 www.c.com 的cookie 已经设置成功

在线演示及代码下载

snippets/crossdomain.txt · 最后更改: 2010/03/31 08:06 由 lost
 
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki