什么是跨域以及几种简单解决方案

什么是跨域?

要明白什么是跨域以前,首先要明白什么是同源策略php

同源策略就是用来限制从一个源加载的文档或脚本与来自另外一个源的资源进行交互。那怎样判断是不是同源呢?html

若是协议,端口(若是指定了)和主机对于两个页面是相同的,则两个页面具备相同的源,也就是同源。也就是说,要同时知足如下3个条件,才能叫同源:ajax

  1. 协议相同
  2. 端口相同
  3. 主机相同

举个例子就一目了然了:json

咱们来看下面的页面是否与 http://store.company.com/dir/index.html 是同源的?segmentfault

  1. http://store.company.com/dir/index2.html 同源
  2. http://store.company.com/dir2/index3.html 同源 虽然在不一样文件夹下
  3. https://store.company.com/secure.html 不一样源 不一样的协议(https)
  4. http://store.company.com:81/dir/index.html 不一样源 不一样的端口(81)
  5. http://news.company.com/dir/other.html 不一样源 不一样的主机(news)

因此当面对跨域问题的时候,有什么解决方案呢?跨域

跨域的几种解决方案

document.domain方法

咱们来看一个具体场景:有一个页面 http://www.example.com/a.html ,它里面有一个iframe,这个iframe的源是 http://example.com/b.html ,很显然它们是不一样源的,因此咱们没法在父页面中操控子页面的内容。dom

解决方案以下:异步

<!-- b.html -->
<script>
document.domain = 'example.com';
</script>
<!-- a.html -->
<script>
document.domain = 'example.com';
var iframe = document.getElementById('iframe').contentWindow.document;

//后面就能够操做iframe里的内容了...

</script>

因此咱们只要将两个页面的document.domain设置成一致就能够了,要注意的是,document.domain的设置是有限制的,咱们只能把document.domain设置成自身或更高一级的父域。函数

可是,这种方法只能解决主域相同的跨域问题。post

window.name方法

window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的全部的页面都是共享一个window.name的,每一个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的全部页面中的,并不会因新页面的载入而进行重置。

咱们来看一个具体场景,在一个页面 example.com/a.html 中,咱们想获取 data.com/data.html 中的数据,如下是解决方案:

<!-- data.html -->
<script>
window.name = 'data'; //这是就是咱们须要通讯的数据
</script>
<!-- a.html -->
<html>
<head>
<script>
    function getData () {
        var iframe = document.getElementById('iframe');
        iframe.src = 'example.com/b.html'; // 这里让iframe与父页面同源
        
        iframe.onload = function () {
            var data = iframe.contentWindow.name; //在这里咱们获得了跨域页面中传来的数据
        };
    }
</script>
</head>
<body>
</body>
</html>

JSONP方法

JONSP(JSON with Padding)是JSON的一种使用模式。基本原理以下:

<!-- a.html -->
<script>
    function dealData (data) {
        console.log(data);
    }
</script>

<script src='http://example.com/data.php?callback=dealData'></script>
<?php
    $callback = $_GET['callback'];
    $data = 'data';
    echo $callback.'('.json_encode($data).')';
?>

这时候在a.html中咱们获得了一条js的执行语句dealData('data'),从而达到了跨域的目的。

因此JSONP的原理其实就是利用引入script不限制源的特色,把处理函数名做为参数传入,而后返回执行语句,仔细阅读以上代码就能够明白里面的意思了。

若是在jQuery中用JSONP的话就更加简单了:

<script>
$.getJSON(''http://example.com/data.php?callback=?', function (data) {
    console.log(data);
});
</script>

注意jQuery会自动生成一个全局函数来替换callback=?中的问号,以后获取到数据后又会自动销毁,实际上就是起一个临时代理函数的做用。$.getJSON方法会自动判断是否跨域,不跨域的话,就调用普通的ajax方法;跨域的话,则会以异步加载js文件的形式来调用JSONP的回调函数。

总结

除了上述方法外,HTML5还新增了一个window.postMessage()方法,有兴趣的能够自行查阅。

最后,解决跨域问题还有一个更通用更强大的CORS方法,我单独把它拿出来总结了一篇文章:跨域问题的根本解决方案CORS

相关文章
相关标签/搜索