什么是跨域?当两个域具有相同的协议、相同的端口、相同的host时,那么我们就可以认为它们是相同的域。比如:http://www.example.com/a.html 和 http://www.example.com/b/c.html 就属于相同的域,数据访问可通过 ajax 解决。反之如果不符合上述三个条件中任何一个,我们称之为不同域。比如 http://www.example.com/a.html 和 http://example.com/b.html。由于javascript同源策略的限制,js 语言本身是不具备跨域访问能力的,但是很多时候业务需求,加之程序员们丰富的想象力,出现了各种解决跨域问题的方案。这里就对比较主流的跨域方案做一个简单的汇总。

Image Beacon

这种跨域方案非常简单,利用的是图片可以跨域读取的性质,代码如下:

  var img = new Image();

  img.src = "http://example.com/data?value=123";

在 js 里执行上述两行代码,就可以向 http://example.com/data 传送数据了,而不用担心是否和 src 里面的地址不同域。数据部分嵌入在URL中,即"value=123" 部分。

这种方案优点在于非常简单,不会带来很多代码的管理问题。缺点在于它只能单向的给服务发送数据,再者由于数据嵌入在 URL 中,而URL的字符长度是受浏览器限制的,所以数据大小也会有限制。

Image Beacon 对于第三方的统计网站非常有用。百度统计、CNZZ等均有用到。

JSONP

JSONP 跨域算是用的比较多的了,研究下QQ空间,就会发现里面很多用了JSONP技术。JSONP利用的是 script 标签跨域请求 js 文件的能力。实现方式如下:

1)首先建立一个动态 script 标签

  var script = document.createElement('script');

  script.src = 'http://example.com/data?callback=fn';

  document.body.appendChild(script);

2)注意上面的 src 部分,最后面带有参数 callback=fn。fn 必须是一个全局函数,且要在在 script 标签 append 到 body 里面之前要声明好的。

  function fn(data) {

    // 对data 进行处理

  }

3)步骤1完成之后,script 标签动态的生成在 body 标签内。浏览器解析到script标签,给服务器(http://example.com)发送请求。服务器接受到请求后,将需要传给客户端的数据以json格式包在 fn 函数中,以参数的形式传进去,如下:

  fn({value: 123});  //服务端传给客户端的 js

4)浏览器接受到服务器端传来的 js 代码,执行,发现 fn 函数已经声明在全局中了(步骤2),于是数据成功的传到了 js 代码中。

这种方式好处在于可以在客户端和服务器端传输数据,且不受长度限制。缺点在于由于是第三方服务器传来的值,安全性不可控,所以在上述例子中,fn 函数在操作data之前,必须对data进行校验,以保证没有恶意代码注入。

iframe 通信

有主页面A,嵌入一个iframe B(name 属性设为 "B"),A和B之间的通信可以分两种情况,一种A和B同域,一种A和B不同域。

1)A和B同域

由于是同域,浏览器允许他们之间互相访问,访问方式如下:

  A访问B:winB = window.frames["B"].window;    //winB 指向B中的window对象

  B访问A:winA = parent.window;  //winA 指向A中的window对象

2)A和B不同域

不同域的时候,上述访问就要出错了。由于安全问题,浏览器限制了不同域之间 js 访问权限。既然 js 直接访问失败,有没有其他方式可以实现主页面和不同域的 iframe 之间的通信呢?这个时候就要发挥程序员的 hack 精神了,下面的内容为跨域的情况,分两种情况讨论。

a)主页面A传数据给iframe B

    在A中设置B的src属性形式如下:

    <iframe src="http://b.com/hello#data" name="B"></iframe>

  data即是A要传给B的值,此时B中可以通过 location.hash 来获取data的值了。

  利用URL的hash传值,好处在于当通过js修改hash值时(URL改变),不会导致iframe 整个刷新。这样的话,如果需要A持续的给B传值,就可以不断的修改URL后面data的值了,而B可以通过onhashchange监听hash值的改变。低端浏览器由于不支持onhashchange,可以通过设置setInterval 来监听URL是否有改动,从而获得改动后的hash值。

b)iframe B 给主页面A传数据

  在 iframe B 中再嵌入隐藏的一个 iframe C,设置iframe C 和主页面A同域但不同URL。假设A的url为 http://a.com,那么iframe C设置如下:

    <iframe src="http://a.com/iframe_c#data" name="C"></iframe>

  同样,URL中的hash部分为iframe B需要传给A的值。由于A和C之间是同域关系,是可以通过js直接访问的。因此只需要在C中通过JS获取到C的URL中data部分,然后传递给A就行了,实现代码如下:

    parent.parent.fn(location.hash);

  注意在执行上面这行代码之前必须在A中声明好全局函数fn,parent.parent 指向的即主页面A中的window对象。

主页面与iframe 之间的跨域通信还可以利用 window.name 这个属性的特殊性来达到。具体就不做说明了,有兴趣的同学可以在网上搜搜。跨域的方式很多,关键是选择一种即能满足本身的业务需求又不影响到代码的可维护性和扩展性。这篇文章算是一个总结,抛砖引玉。前端是个大坑,进去容易,要想明明白白的出来,还得费一番功夫。

javascript 跨域汇总的更多相关文章

  1. JavaScript 跨域漫游

    前言: 最近在公司做了几个项目都涉及到了iframe,也就是在这些iframe多次嵌套的项目中,我发现之前对iframe的认识还是比较不足的,所以就静下心来,好好整理总结了iframe的相关知识:&l ...

  2. 利用javascript跨域访问cookie之广告推广

    在上一篇<说一说javascript跨域和jsonp>中,利用JSONP进行了跨域的数据访问,利用JS本身的跨域能力在远端生成HTML结构的方式完成了一个小广告. 在实际应用中, 跨域使用 ...

  3. Javascript跨域问题总结

    疯狂的JSONP 关于JSON与JSONP简单总结 window.name实现的跨域数据传输 JavaScript跨域总结与解决办法 flash跨域策略文件crossdomain.xml配置详解

  4. 优雅绝妙的Javascript跨域问题解决方案

    关于Javascript跨域问题的解决方案已在之前的一片文章中详细说明,详见:http://blog.csdn.net/sfdev/archive/2009/02/13/3887006.aspx: 除 ...

  5. JavaScript 跨域:window.postMessage 实现跨域通信

    JavaScript 跨域方式实现方式有很多,之前,一篇文章中提到了 JSONP 形式实现跨域.本文将介绍 HTML5 新增的 api 实现跨域:window.postMessage . 1 othe ...

  6. JavaScript跨域实现

    最近在做个上传文件的服务,其中包含一个上传的web页面.目的是想客户端页面嵌套这个web页面,然后直接将文件上传到服务器. 因为文件不同所以需要保存到的文件夹名称也不一样,所以客户端需要传递一个文件夹 ...

  7. thinkphp,javascript跨域请求解决方案

    javascript跨域请求解决方案 前言 对于很多前端或者做混合开发的同学,我们难免会遇到跨域发起请求业务,比如A站点向B站点请求数据等等.由于最近要做一个站点集群的项目,所以具体业务要求很多个站点 ...

  8. JavaScript 跨域之 POST 实现。

    javascript 跨域是一个很常见的问题,其中 jsonp 是一个最常用的手段,但是 jsonp 只支持 get,不支持 post,所以如果想通过 jsonp 来 post 一些数据,就头大了. ...

  9. jQuery(三) javascript跨域问题(JSONP解决)

    加油~ --WH 一.什么是javascript跨域问题? 域:服务器域名,唯一标识(协议,域名,端口)必须保证一致,说明域相同 跨域:在一个服务器上,去访问另一个服务器上,并且得到另一个服务器返回回 ...

随机推荐

  1. linux中如何使用微软鼠标的第4、5键

    虽说使用linux的 人大都对微软没什么好感,但不能否认微软确实也出了不少好东西呀,比如微软鼠标(IE系列) icon_smile.gif IE 2.0和以上版本都有5个按钮,除了正常的左中右外,两侧 ...

  2. SQL Server索引的维护 - 索引碎片、填充因子 <第三篇>

    实际上,索引的维护主要包括以下两个方面: 页拆分 碎片 这两个问题都和页密度有关,虽然两者的表现形式在本质上有所区别,但是故障排除工具是一样的,因为处理是相同的. 对于非常小的表(比64KB小得多), ...

  3. 关于set和map的用法

    1.set 定义:每个元素最多只出现一次,并且默认的是从小到大排序. set 遍历: 题目http://www.cnblogs.com/ZP-Better/p/4700218.html for(set ...

  4. No enclosing instance of type Outer is accessible. Must qualify the allocation with an enclosing instance of type Outer (e.g. x.new A() where x is an instance of Outer)

    之前看内部类的时候没发现这个问题,今天写代码的时候遇到,写个最简单的例子: 下面这一段代码 红色的部分就是编译报错: No enclosing instance of type Outer is ac ...

  5. 查看Java包源码

  6. 1 游戏逻辑架构,Cocos2d-x游戏项目创建,HelloWorld项目创建,HelloWorld程序分析,(CCApplicationProtocol,CCApplication,AppDeleg

     1 游戏逻辑架构 具体介绍 A 一个导演同一时间仅仅能执行一个场景,场景其中,能够同一时候载入多个层,一个层能够可载多个精灵.层中亦能够加层. B  场景切换 sceneàaddChild(la ...

  7. 有关docker新版的icc、iptables的一个巨坑

    之前玩过docker的icc=false.iptables=true 按照这两个参数配置之后,想指定两个特定的容器通讯,直接用--link即可. 但最近我在下载了1.12新版的docker,这个不奏效 ...

  8. [python笔记][第二章Python序列-list]

    2016/1/27学习内容 第二章 Python序列-list list常用操作 list.append(x) list.extend(L) list.insert(index,x) list.rem ...

  9. 【巧妙预处理系列+离散化处理】【uva1382】Distant Galaxy

    给出平面上的n个点,找一个矩形,使得边界上包含尽量多的点. [输入格式] 输入的第一行为数据组数T.每组数据的第一行为整数n(1≤n≤100):以下n行每行两个整数,即各个点的坐标(坐标均为绝对值不超 ...

  10. LINQ 基本子句之二 join

    Join子句据说可以实现3中连接关系. 1.内部连接——元素的连接关系必须同时满足被连接的两个数据源 2.分组连接 3.左外连接 1.最基本的,内部连接,类似于sql中inner join. 由于st ...