JavaScript中的跨域详解(内附源码)

什么是跨域?

什么是跨域?

所谓跨域,就是如果在不同的域名下面存在数据交互,这个时候就会存在跨域的问题,这里要说明的是在同一个网站不同的文件夹下的数据交互是不存在跨域问题的。

哪些情况下存在跨域问题?

  • 主域和子域之间会存在跨域问题(比如 www.a.comwww.a.b.com)。

  • 不同的域名存在跨域问题,哪怕这两个域名指向的是同一个ip地址。

为什么 ajax 不可以跨域?

因为 ajax 是通过 XMLHttpRequest 这个对象来进行数据之间的交互的,而 XMLHttpRequest 为了安全起见是不允许跨域交互数据,所以 ajax 是不可以跨域的。

跨域问题的几种解决方式?

1.jsonp

什么是 jsonpjsonp = json + padding (内填充)。其实他就是利用了内填充的原理把 json当做一个内填充的东西,填充到一个盒子当中,比如说,像下面这样:box{{name:"laowang"}};

jsonp有一个缺点就是只能单域操作,就是我们不可以通过本网站去修改其他网站的数据。

使用 jsonp 来进行跨域是平时比较常用的,用 script 标签的形式,script 标签不存在跨域的问题,我们也把它统称为 jsonp 的形式。

我们可以把 script 里面的 src 当做请求的地址,你要知道 script 标签不是仅仅只能请求 js文件,比如说它还可以请求 php。只要是这个页面运算完返回的结果是 json 或者是 js 它就不会有问题。

实例一:

</head>
<body>
<script type="text/javascript"> //a.com </script>

<!-- 假如我们这里引入的是b网站的php文件, a网站的数据就可以通 过 src 传送到 b 网站,a 网站的数据是加到问号后面的,然后数据 在 b 网站进行运算,最终把返回的结果输出出来,那我们在 a 网站中 就可以调用到b网站的数据了-->

<script type="text/javascript" src="b.php?key=value&key2=value2"></script>
</body>

实例二:

(jsonp.html)

<body>
<script type="text/javascript"> //a.com //注意这里名字要一样,即 box function box(json){ //这个时候在 a 网站下我们就可以取到这个 name 值了 alert(json.name); } </script>

<script type="text/javascript" src="1.jsonp.js"></script>
</body>
(jsonp.js)

//b.com
//我把数据写到盒子里面之后,我这个数据是在 b 网站的地址下面
//的,而我们要调用的时候就可以利用回调的原理进行调用。

box({name : 'laowang'});

效果展示 || 源代码

动态创建 jsonp

(jsonp.html)

<script type="text/javascript"> function createJs(sUrl){ var oScript = document.createElement('script'); oScript.type = 'text/javascript'; oScript.src = sUrl; document.getElementsByTagName('head')[0].appendChild(oScript); } createJs('jsonp.js?callbcak=box'); //这个 box 必须和 jsonp 中的 box 一致,但是有的时候, //你不知道这个名字是什么,那我们就可以自己写一个参数加进去 //从而让自己来来控制这个名字  //即:?callbcak=box function box(json){ alert(json.name); } </script>
(jsonp.js)

box({name : 'laowang'});

效果展示 || 源代码

2.location.hash

可以利用 location.hash 值进行跨域,因为我们跨域无非就是发送一个请求,然后取得页面的数据。我们可以通过 iframe 利用 location.hash 来进行跨域操作。这个方法的优点就是可以进行双域操作。

原理:比如说我在 a 网站上嵌套了一个 b 网站的 iframe 这个时候,我们就可以把数据添加到用 script 标签引入的 php 的哈希值上,即 src="xxx.php#key1=value&amp;key2=value2",哈希值加完之后不会改变页面的网址,这样可以把数据带到 b 网站,然后 b 网站就可以根据数据进行解析,返回数据,然后a 网站可以通过 parent.location.hash 来更新本页面的 hash 值,那这个时候 a 网站就可以获取到 b 网站上的数据了。

但是这个方法是另一个域下面的,为了安全起见,有的浏览器是不支持的,比如说 iechrome,咱们没办法直接从另一个域上面找到它的父级,这样的话咱们就可以通过在 a 网站的页面当中再去创建一个 a 网站的页面。

比如说创建一个新的页面 yyy.html,他也是 a网站的,然后把数据添加到 a 网站的 yyy.html 这个页面中,添加号之后呢,这个时候我们就可以在 a 网站通过这个方法 parent.location.hash = self.location.hash获取数据, 因为他们现在是同一个域下面的,这样子就可以通过改变
hash 值,来进行这两个域之间的数据交互。

3.window.name

还可以用 window.name 来解决跨域的问题,这个是比较安全的,因为内容写到了 `window.name 上,不会暴露出来。

window 对象有个 name 属性,该属性有个特征:即在一个窗口 (window) 的生命周期内,窗口载入的所有的页面都是共享一个 window.name 的,每个页面对 window.name 都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的。

原理:现在有两个网站,这两个网站下面各有一个页面 www.a.com -->a1.html 和 www.b.com -->b1.html,然后我们也是通过在 a 网站的 a1.html 下面创建一个 iframe标签,然后 src 指定的就是 b 网站数据的 b1 这个页面,然后我们在 b 网站的 b1.html window.name = '数据';下面去写数据就可以了。

写完之后,当 a1 加载完之后,我们在 b1 下面去创建 a1 的一个代理文件,www.b.com --> agent.html,创建完之后,代理文件和 window.name 是共用数据的,这个时候当我再请求 a1.html 的时候,就可以通过代理来取到数据了。

这个和 hash 的原理其实是差不多的,都是在自己的域下面创建一个当前要用数据那个域的一个代理文件,然后再通过代理和当前文件在同一个域下的一个原则,然后把数据提交过去。

个人认为 window.name 的方法既不复杂,也能兼容到几乎所有浏览器,这真是极好的一种跨域方法。

4.document.domain

在子域和主域之间都设置 document.domain = '主域名的网址';

将子域和主域的 document.domain 设为同一个主域.前提条件:这两个域名必须属于同一个基础域名!而且所用的协议,端口都要一致,否则无法利用document.domain进行跨域。

5.服务器代理

不同的域名下通过服务器代理解决:服务器代理是通过在服务器下面做这对象XMLHttpRequest 的代理文件,然后服务器去做运算,他的优点是你可以做到任何一想要的数据交互,而它的缺点是会增大服务器的压力。

6.flash

flash也可以解决跨域的问题。

7.postMessage

postMessagehtml5的方法,有兴趣的同学可以自己去看一下。

你可能感兴趣的:(jsonp,跨域,Ajax,hash,window-nam)