导语 | 在日常开发过程中,我们通常都会遇到ajax跨域请求或者前端跨域通信的开发场景。无论是前端同学还是后端同学都需要具备解决跨域问题的能力。本文总结梳理了常见的跨域场景、跨域解决方案及其优缺点,希望可以作为大家解决跨域问题的参考。
一、什么是跨域
当a.qq.com域名下的页面或脚本试图去请求b.qq.com域名下的资源时,就是典型的跨域行为。跨域的定义从受限范围可以分为两种,广义跨域和狭义跨域。
(一)广义跨域广义跨域通常包含以下三种行为:
资源跳转:a链接、重定向。
资源嵌入:、代码语言:javascript代码运行次数:0运行复制document.domain+iframe方案优点:
实现逻辑简单,无需额外中转页面document.domain+iframe方案缺点:
仅适用于主域相同,子域不同的前端通信跨域场景
location.hash+iframe当两个不符合同源策略且主域不同的页面需要进行跨域通信时,可以利用url的hash值改变但不刷新页面的特性,实现简单的前端跨域通信。
通常情况下http://a.qq.com/a.html内嵌不同域的http://b.qq1.com/b.html时,受浏览器安全机制限制,a.html 可以修改b.html的hash值,但b.html不被允许修改不同域的父窗体a.html的hash值。因此,此方案需要一个与a.html同源的http://a.qq.com/c.html来进行中转,此方案实现流程如下图所示:
location.hash+iframe方案代码示例:
代码语言:javascript代码运行次数:0运行复制代码语言:javascript代码运行次数:0运行复制代码语言:javascript代码运行次数:0运行复制location.hash+iframe方案优点:
可以解决主域不同的前端通信跨域问题。hash改变,页面不会刷新。location.hash+iframe方案缺点:
受部分浏览器安全机制限制,需要额外的同源中转页面,且中转页面需要js逻辑来修改hash值。通信数据类型及长度均受限,且数据外显在url上,存在一定安全风险。
window.name+iframewindow.name属性的独特之处在于,name值在不同页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的name值(2MB)。
如下图所示,http://a.qq.com/a.html内嵌不同域的http://b.qq1.com/b.html。b.html有数据要传递时,把数据附加到window.name上,然后跳转到一个和a.html同域的http://a.qq.com/c.html。由于a.html和c.html满足同源策略,a.html可以获取c.html的window.name,从而实现了跨域通信。
window.name+iframe代码示例:
代码语言:javascript代码运行次数:0运行复制代码语言:javascript代码运行次数:0运行复制window.name+iframe方案优点:
可以解决主域不同的前端通信跨域问题。通信数据类型不受限,且长度可达2MB。window.name+iframe方案缺点:
需要额外的同源中转页面,但中转页可以为空白页。
postMessagepostMessage是HTML5 XMLHttpRequest Level2中的API,且是为数不多可以跨域操作的window属性之一,它通常用于解决以下方面的问题:
页面和其打开的新窗口的数据传递。多窗口之间消息传递。页面与嵌套iframe消息传递。postMessage是一种安全的跨域通信方法。当a.html获得对b.html的window对象后,a.html调用postMessage方法分发一个MessageEvent消息。b.html通过监听message事件即可获取a.html传递的数据,从而实现跨域通信。postMessage实现流程如下图所示:
postMessage方法的语法如下:
otherWindow.postMessage(message、targetOrigin、[transfer])
otherWindow
目标窗口的window对象,比如iframe的contentWindow属性、执行window.open返回的window对象等。
message将要发送给其他window的数据。
targetOrigin指定哪些窗口能接收到消息事件,其值可以是字符串*(表示无限制)或者是“协议+主机+端口号”。
transfer(可选)
是一串和message同时传递的Transferable对象,这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。
postMessage方案代码示例:
代码语言:javascript代码运行次数:0运行复制代码语言:javascript代码运行次数:0运行复制postMessage方案优点:
可以解决多种类型的前端跨域通信问题;postMessage方案缺点:
兼容性方面相对差一点,IE8及以下浏览器不支持该方法,IE9只支持postMessage传递string类型的数据,而标准的postMessage消息数据可以是任何类型。
四、总结
本文介绍了浏览器受同源策略限制的跨域行为以及常见的跨域场景。总结了跨域问题的经验,并从ajax请求和前端通信两大方向进行梳理常用的跨域解决方法及其优缺点,希望可以作为大家在日常开发解决web跨域问题的参考。如果有描述不当之处,也希望大家随时进行沟通和指正。
参考资料:
1.浏览器的同源策略
2.跨源资源共享(CORS)
3.Cross-domain AJAX using Flash
4.window.postMessage
作者简介
刘孟
腾讯前端开发工程师
腾讯前端开发工程师,毕业于上海大学。目前负责腾讯优联项目的前端开发工作,有丰富的系统平台及游戏营销活动前端开发经验。
推荐阅读
10分钟带你玩转Kafka基于Controller的领导选举!
LLVM极简教程:9个步骤!实现一个简单编译器
避坑指南!手把手带你解读html2canvas的实现原理
10分钟了解Flutter跨平台运行原理!