前端开发各种cross之cross domain

作为一个苦逼前端开发工程师,不得不面对各种cross,比如面对五花八门的浏览器我们必须cross browser,面对各种终端,我们必须cross
device,在这么多年的前端开发经历中,在不同的域之间穿越中,遭受各种折磨,所以这次和大家分享的是cross domain。

这次分享的cross
domain,是包括所有跨域调用,无论是跨域获取数据,还是跨域跨frame调用,所以会分为两部分,这次会先分享跨域获取数据,跨域获取数据大概有以下方式。

1.jsonp方式
这是最简单,也是最实用的跨域获取数据方式,原理是在浏览器端通过生成script标签,并通过js
callback的形式实现跨域访问,比如一个jsonp接口是这样:
http://mail.163.com/someapp/jsonp?somequery=xxx&callback=fSomeMethod
然后服务器端会通过以下方式返回数据:
fSomeMethod({返回的json数据对象})
优点:实现简单,使用灵活,并且原生cross
all browser
缺点:只能get方式获取数据,某些浏览器会显示加载中提示

2.表单post方式
这个方式会复杂一点点,原理是post表单到一个隐藏的iframe,然后iframe将数据post回来同域的一个url,这时候就可以直接调用同域的回调:
首先post表单到如:http://other.domain.com/someapp?somequery=xxx&callback=fSomeMethod&backurl=http://mail.163.com/proxy
这个接口返回的内容:
<form
action="${backurl}" method="post">
<input type="hidden" name="data"
value="返回的数据">
<input type="hidden" name="callback"
value="${callback}">
</form>
<script>document.getElementsByTagName("FORM")[0].submit();</script>

然后post到http://mail.163.com/proxy后,返回:
<script>
parent.${param.callback}("${param.data}")
</script>
这样就完成整个跨域获取数据的过程
优点:支持post方式,并且原生cross
all browser
缺点:实现有点复杂,并且流程有点曲折,需要两次请求,而且表单post方式会引起刷新提示的问题

3.服务器代理
服务器代理方式跨域调用也是使用的比较广泛的方式,原理就是在服务器端来获取跨域数据,然后在同域里ajax方式或者其他方式返回给浏览器。
优点:客户端实现简单,没有cross
browser问题
缺点:需要在服务器端实现模拟请求获取数据

4.html5的XDomainRequest
终于在html5迎来了对跨域的ajax,泪牛满脸啊,这下完全可以通过浏览器的原生方式跨域ajax获取数据,这里有个对浏览器的各种跨域ajax的测试:
http://www.debugtheweb.com/test/teststreaming.aspx
优点:浏览器原生支持跨域方式ajax请求
缺点:只能在支持html5的高级浏览器中支持

5.flash request
这个是目前跨域请求最好的一个解决方案,建议在不能用jsonp的方式时候,都可以使用flash
request方式,而且flash
request可以配置一个安全策略,可以允许哪些域可以调用,然后被跨域的调用需要配置一个crossdomain.xml,允许可以被那个域的flash跨域调用,内容如下:
<?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="www.xxx.com"
/>
</cross-domain-policy>
这种方式的局限就是必须依赖flash,我们在邮箱曾经做过一个统计,99%的用户可以通过这种方式获取到数据,另外1%的用户可能是没有安装flash或者flash版本有问题。
优点:依赖flash下可以无视各个浏览器兼容问题
缺点:正所谓成也萧何败也萧何,缺点也是因为要依赖flash

以上每个方式都有优点和缺点,具体使用那种方式来跨域获取数据,需要具体使用时候来决定,没有那种方式是完美的。

二:

苦逼的前端开发工程师,刚才解决了一个cross domain的问题,还没有来得及沉浸在其中喜悦之际,又迎来了另外一个cross
domain的问题:邮箱出现双滚动啦。

在页面中当需要加载外域app的iframe时候,最容易出现跨frame的cross
domain问题,比如刚才那前端开发工程师遇到的双滚动的问题,在页面中放入一个外域的iframe,当iframe的高度大于iframe的页面的body高度时,就会出现滚动,这时候加上本身页面已经有一条滚动,那就出现经典的双滚动问题,如果iframe里面又嵌套另一个外域iframe,那可能会出现三滚动,继续嵌套..继续滚动..继续套..继续滚...,之所以出现这个问题,是因为外域的iframe不能直接调用:

parent.document.getElementById("iframe_id").style.height =
document.body.offsetHeight + "px"

这里就需要跨iframe进行cross
domain,有以下提到的两个方式。
以下的例子会以这几个页面作为例子:
页面a:http://www.a.com/a.htm
页面b:http://www.b.com/b.htm
a的内容:<iframe
src="http://www.b.com/b.htm" id="ifrm_b"></iframe>

1.html5的postMessage方式
首先介绍一个浏览器原生的跨域调用方式,在支持html5的高级浏览器,支持这种方式:
oWin.postMessage(oMessage,
sTargetDomain);
oWin为需要跨域调用的window对象
oMessage为传送的数据
sTargetDomain是跨域的frame的域
假如页面a跨域页面b,那么在页面a上调用以下进行跨域:

try{

document.getElementById("ifrm_b").contentWindow.postMessage(JSON.stringify({value:"this
is cross call by PostMessage."}), "http://www.b.com");
}catch(e){

alert("请使用以下或者更高版本浏览器:\nIE8+, Firefox 3, Opera 9, Chrome 3和 Safari
4!");
}

然后在b,需要加一个window的message事件监听
fAddEvent(window, "message", function (o)
{
var oMessage = o.data;// data属性就是postMessage的oMessage参数

alert(oMessage.value); // 这时候会显示:this is cross call by PostMessage.
});

这样就完成了跨frame的跨域通讯
优点:完美的跨frame跨域调用
缺点:只支持html5的浏览器
2.代理iframe方式
使用代理iframe的方式有两种,一种通过window.name方式跨域调用,一种是通过url参数的方式传递调用,不过两种方式的调用原理都是创建一个隐藏的iframe,iframe的url指向需要跨域的域名的一个代理页面,然后通过这个代理的iframe,和跨域的iframe通讯,因为这时代理的iframe和跨域的iframe完全同域,就可以畅通无阻进行。
在上面的例子加多一个代理页面c:
代理iframe
c:http://www.b.com/c.htm
在页面a加入以下函数:

function fCrossByName(sDomain, oData) {
var oIframe =
document.getElementById("ifrmCross");
if(oIframe){

oIframe.parentNode.removeChild(oIframe);
}
oIframe =
document.createElement("IFRAME");
oIframe.style.display = "none";

oIframe.id = "ifrmCross";
oIframe.name = JSON.stringify(oData);

document.body.appendChild(oIframe);
oIframe.src = "http://" + sDomain +
"/c.htm";
}

然后在页面a就可以进行跨域:
fCrossByName("www.b.com", {
value:‘this is cross call
by iframe‘,
func : "fCrossByNameCall", // 要跨域调用的函数
win :
"ifrm_b"
});

然后在代理iframe加入以下代码:
var oData = !window.name?null:(new Function(‘return
‘+window.name))();
if(oData.win && oData.func){
var oResult =
(oData.win == "top" ? top : parent[oData.win])[oData.func](oData);
}

这样就可以实现整个的跨域调用,通过url参数方式跨域调用,和这个类似,只是需要将数据放到代理iframe的url参数上,而不是name。
下面这个页面demo显示这三种方式的调用(因为没加JSON的转换js包,需要使用支持内置JSON对象的浏览器运行..):
http://mimg.163.com/demo/crossdomain_test.htm
优点:没有浏览器兼容问题
缺点:因为要部署代理iframe的文件,所以比较麻烦,整个流程也比较复杂,如果要实现和html5的postMessage兼容的接口,需要做大量封装,就会更加造成更加复杂

总结:在邮箱实际使用过程中,当只是简单的跨域调用比如前面提到的解决双滚动问题,一般可以简单的使用第二种方式,但是如果需要复杂的双向互相调用,就需要支持html5的浏览器调用postMessage,不支持的需要第二种方法实现兼容。

原文链接:http://ntesmailfetc.blog.163.com/blog/static/206287061201241011546581/

前端开发各种cross之cross domain,布布扣,bubuko.com

时间: 2024-10-12 22:17:46

前端开发各种cross之cross domain的相关文章

前端开发常见的缩写词中英文对照

趁着周末总结一下我们作为前端开发人员,需要掌握的一些缩写的词,这次总结的都是概念中的内容,不包括流行的框架,库等的名词. 关于框架和库的名词介绍,欢迎关注我后续的更新. AJAX ==[Asynchronous Javascript And XML]--[异步的javascript和XML] AMD ==[Asynchronous Module Definition]--[异步模块加载机制] API ==[Application Programming Interface]--[应用程序编程接口

在Mac OSX下设置前端开发环境

以下内容将会详细介绍本人在MAC OSX下关于前端开发环境的安装和设置,如果您是前端开发人员,并且手上有个全新的或者重新安装过系统的mac,你可能会在以下内容里发现你所需要的东西. Google Chrome 几乎是每个前端开发者必备的浏览器,下载地址: https://www.google.com/chrome 一些常用到得Chrome插件: [JSON Formatter(显示格式化过得JSON文件)](https://chrome.google.com/webstore/detail/js

前端开发工程师如何在2013年里提升自己【转】--2016已更新升级很多何去何从?

大部分人非常在意个人在技术上的提升.但是保持对新技术的了解是一项不小的挑战, 毕竟我们需要的信息在数量上过于庞大.2012年里,伴随着前端发展的是大量的革命性突破和对前端的重新定义. 我们在实践的路上飞速前进,具体的进步体现在使用抽象化,优秀的代码质量,维护性上的提升以及更好的性能.如果你实在忙到没有时间来跟上最新的技术,不用担心. 随着假日的来临,我们就有了一些空闲的时间可以自己支配,我想,如果我把我收集的前端相关的精品讨论列表分享出来,那一定会对大家有一些帮助.你不需要把所有的都阅读一遍,但

关于前端开发中的“收口”思想

什么是收口 所谓条条大路通罗马,但如果让我来设计通向罗马的各种大路,我至少会做两件事情: ① 让罗马只有一个入口 ② 让罗马只有一个出口 这样做的好处是,无论你路从哪来,我可以统一在入口处给你打上各种标志,我也可以在你离开罗马时给你留点纪念.当然罗马自然不只一个出口入口,但是每个出口入口一定有一套相同的规定,否则就会出问题. 具体到当今的工作场景,高速公路又是一个收口的好例子,进入高速公路时候得经过收费站做点标志,离开时候也会做点操作,如果没有这种收口,不论是缴费工作,流量统计或者其他都是无法统

web前端开发程序员面试题集锦

随着web前端开发的越来越火热,学习web前端开发的朋友也逐渐变多,学完之后面试web前端程序员(http://www.maiziedu.com/course/web-px/)时,面试官会提出一些面试题,那么面试官一般会问哪些前端开发面试题呢,小编整理了一份,仅供大家参考: 1. em  和 strong  的区别 em 表示强调,strong 表示更强烈的强调.言简意赅,表明了 em 和 strong 的命名来历.并且在浏览器中,em 默认用斜体表示,strong 用粗体表示 2.请用CSS实

前端开发工具—fiddle

1.Fiddler相对其他调试工具的优势 HttpWatch 和 Firebug绝大多数前端开发人员都比较熟悉,但是HttpWatch虽然可以抓到每个 HTTP 请求的全部数据,但无法修改返回的数据:尽管Firebug可以修改 HTML和CSS,但是在调试CGI接口时无法干预HTTP请求的参数值和CGI返回的数据.而 Fiddler作一个 HTTP 调试代理,不但能够记录客户端同服务器之间的所有 HTTP 通讯数据,还能够修改请求数据和返回数据,也叫做“构造请求”和“模拟响应”.除此之外, 添加

前端开发之常用方法

在进行前端开发中,经常会使用一些常用的方法来解决问题,汇总在此. 一 表单相关 1)获取下拉框的值 $('#名称').val(); //直接定位元素,获取值即可 2)获取单选框/复选框的值 $('元素 :checked').val(); //定位元素并且是被选中的,获取其值即可 3)文本框 resize:none; //禁止文本框被拖拽 二 js初始化加载 1)在body里面写初始化方法 <body onload='init()'> </body> <script type=

7招提升你的前端开发效率

7招提升你的前端开发效率 前言 前端工程师其实是一个工作很杂的职位,除了要负责切图.写html/css/js外,还要解决一系列的浏览器兼容性.网页性能优化等问题,所以提高前端工程师的开发效率是势在必行的,也是前端工程化的体现. 对于开发效率,我个人理解是 开发效率 = 新增代码的效率 + 修改代码的效率 + 维护代码的效率 那么如何提高前端开发效率便可以按照前端工程化的理念来进行划分.下面我就介绍下7个提高前端开发效率的方法. 前端工程化 方法 1.切图 切图是一个前端最基础的技能,一般我们使用

前端开发笔记(2)css基础(上)

CSS介绍 层叠样式表(英文全称:Cascading Style Sheets)是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言.CSS不仅可以静态地修饰网页,还可以配合各种脚本语言动态地对网页各元素进行格式化.CSS 能够对网页中元素位置的排版进行像素级精确控制,支持几乎所有的字体字号样式,拥有对网页对象和模型样式编辑的能力. <style type="text/css"> span{ color:red;