DOM跨域的三种解决方案:document.domain、window.name、window.postMessage
文章目录
- 同域访问
- document.domain
- 相同二级域名之间的跨域
- 相同域名,不同端口之间的跨域
- window.name
- window.postMessage
同域访问
浏览本篇文章之前,需要了解什么是跨域,就需要了解浏览器的同源策略,简单来说就是协议
,域名
,端口
,这三者都一样才称之为同源,详细的浏览器同源策略可以浏览文章:浏览器的同源策略
同域的不同页面之间通信可通过自定义事件和监听事件的方式实现,具体Demo可以参考笔者的另外一篇文章:javascript —— 父页面监听iframe子页面的自定义事件,那么不同域之间的页面怎么进行消息传递呢,本文将介绍三种方式:document.domain
、window.name
、window.postMessage
document.domain
默认情况下,document.domain存放的是载入文档的服务器的主机名,可以手动设置这个属性,设置该属性有两个特点:
- 只能设置成当前域名,或者当前域的二级域名(比如document.domain为 www.baidu.com,可以设置成 baidu.com)
- 任何对document.domain的赋值操作,包括 document.domain = document.domain 都会导致端口号被重写为 null
通过这两个特点,我们就可以实现二级域名相同的不同域之间的跨域dom访问(就算端口不同也可以)
相同二级域名之间的跨域
举个例子:
http://www.qq.com
的document.domain为"qq.com",http://id.qq.com
的document.domain为"id.qq.com",默认情况下,id.qq.com是无法对www.qq.com进行跨域操作的:
但是,如果通过将document.domain设置成"qq.com"就不同了:
相同域名,不同端口之间的跨域
举个例子:
http://http://localhost:3001/window.html
的document.domain为"localhost",http://localhost:3002/b.html
的document.domain也为"localhost",但是他们的端口一个是3001,一个是3002,所以默认情况下,window.html是无法对b.html进行跨域操作的:
现在,我们进行两个操作,分别将window.html
的document.domain和b.html
的document.domain均设置成"localhost",这样它们的端口都会被重置成null,它们的域名和端口都一致,就可以进行跨域访问了
window.html
document.domain = 'localhost'
b.html
document.domain = 'localhost'
window.name
在页面在浏览器端展示的时候,我们总能在控制台拿到一个全局变量window,该变量有一个name属性,其有以下 特征:
- 每个窗口都有独立的window.name与之对应;
- 在一个窗口的生命周期中(被关闭前),窗口载入的所有页面同时共享一个window.name,每个页面对window.name都有读写的权限;
- window.name一直存在与当前窗口,即使是有新的页面载入也不会改变window.name的值;
- window.name可以存储不超过2M的数据,数据格式按需自定义。
作者:Bennt
链接:https://www.jianshu.com/p/43ff69d076e3
来源:简书
我们来看一个当window重新加载后window.name不变的例子:
window.name = "{\"msg\":\"我是传递的数据\"}";
setTimeout(function(){window.location.href="b.html"alert(JSON.parse(window.name).msg);
}, 2000);
结果:
现在假如我们在 localhost:3001/window.html页面,需要获取到 localhost:3002/b.html页面上的数据(注意:端口不同,为跨域),我们可以这么操作:
localhost:3002/b.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head>
<body></body>
<script type="text/javascript">window.name = "{\"msg\":\"我是b页面传递的数据\"}"</script>
</html>
localhost:3001/window.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><style>#inIframe {display: none;}</style>
</head>
<body><h2>主页面</h2><div id="inIframe"></div>
</body>
<script type="text/javascript">/*** 参考文章:JS跨域--window.name* 链接:https://www.jianshu.com/p/43ff69d076e3* 作者:Bennt*/var boo = false;var iframe = document.createElement('iframe');var loadData = function() {if (boo) {var data = iframe.contentWindow.name; // 获取window.nameconsole.log(data); // 销毁数据iframe.contentWindow.document.write('');iframe.contentWindow.close();document.getElementById("inIframe").removeChild(iframe);} else {boo = true;iframe.contentWindow.location = "b.html"; // 设置的代理文件,iframe重新载入} };iframe.src = 'http://localhost:3002/b.html';if (iframe.attachEvent) {// 兼容ie7/ie8iframe.attachEvent('onload', loadData);} else {iframe.onload = loadData;}// id为inIrame通过css设置为了隐藏,这样获取b.html数据过程中不会出现插入和移除iframe过程中的闪现现象document.getElementById("inIframe").appendChild(iframe);</script></html>
window.postMessage
window.postMessage() 方法可以安全地实现跨源通信。通常,只有同源的页面才能相互通信,window.postMessage() 方法提供了一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。
语法
otherWindow.postMessage(message, targetOrigin, [transfer]);
变量名 | 说明 |
---|---|
otherWindow | 其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。 |
message | 将要发送到其他 window的数据。它将会被结构化克隆算法序列化。这意味着你可以不受什么限制的将数据对象安全的传送给目标窗口而无需自己序列化。 |
targetOrigin | 通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串""(表示无限制)或者一个URI。在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。这个机制用来控制消息可以发送到哪些窗口;例如,当用postMessage传送密码时,这个参数就显得尤为重要,必须保证它的值与这条包含密码的信息的预期接受者的origin属性完全一致,来防止密码被恶意的第三方截获。如果你明确的知道消息应该发送到哪个窗口,那么请始终提供一个有确切值的targetOrigin,而不是。不提供确切的目标将导致数据泄露到任何对数据感兴趣的恶意站点。 |
transfer (可选) | 是一串和message 同时传递的 Transferable 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。 |
假如我们通过window.html页面的iframe加载另外一个域的b.html页面,并在b.html页面监听window.html页面发送的消息,在b.html收到消息后,再回消息给window.html,示例代码如下:
loalhost:3001/window.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head>
<body><h2>主页面</h2><iframe id="contentIframe" src="http://localhost:3002/b.html"></iframe>
</body>
<script type="text/javascript">window.onload = function() { console.log('window页面发送消息')document.getElementById('contentIframe').contentWindow.postMessage({code: 1,msg: 'Hello b, i am window.html'}, "http://localhost:3002"); }; window.addEventListener('message', function(event){ // 通过origin属性判断消息来源地址if (event.origin == 'http://localhost:3002') {console.log('window页面收到消息:' + event.data.msg) }}, false);</script></html>
localhost:3002/b.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head>
<body><span>我是b页面</span><br><input type="button" value="回消息" onclick="postmsg()">
</body>
<script type="text/javascript">let parent = null;let origin = null;window.addEventListener('message', function(event){ // 通过origin属性判断消息来源地址if (event.origin == 'http://localhost:3001') {parent = event.sourceorigin = event.originconsole.log('b页面收到消息:' + event.data.msg) }}, false); /*** 回消息方法* * 假设你已经验证了所受到信息的origin (任何时候你都应该这样做), * 一个很方便的方式就是把event.source作为回信的对象,* 并且把event.origin作为targetOrigin*/function postmsg() {console.log('b页面回消息')parent.postMessage({code: 1,msg: 'hi, i am b.html'}, origin)}</script>
</html>
结果:
点击b.html的”回消息“按钮
注意:
任何窗口可以在任何其他窗口访问此方法,在任何时间,无论文档在窗口中的位置,向其发送消息。 因此,用于接收消息的任何事件监听器必须首先使用origin和source属性来检查消息的发送者的身份。 这不能低估:无法检查origin和source属性会导致跨站点脚本攻击。
DOM跨域的三种解决方案:document.domain、window.name、window.postMessage相关推荐
- 同源策略、跨域以及跨域的三种解决方案详解
浏览器并非限制了http发起的请求,跨域请求可以正常发起,但是返回结果会被浏览器拦截. CORS的核心就在于 让服务器来确定是否允许跨域访问. 1.服务器代理: 2.cors跨域资源共享: 3.JSO ...
- 前端交互之“解决前端跨域的三种方法”
1.什么是前端跨域? 跨域是浏览器为了安全而做出的限制策略:浏览器请求必须遵从同源测试: http://www.bilibili.com:8080:/anime/?key=calue路径 键值对 同协 ...
- 前端实现跨域的三种方式
前端解决跨域的三种方式: 1.cors跨域(只需要后端配置) header("Access-Control-Allow-Origin:*"); // 允许任何来源 header(& ...
- 什么是同源策略?解决跨域的三种方法?
1.同源策略 同源策略是一种约定和规范好的安全策略,是浏览器最核心最基本的安全保障.同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据. 满足的条件: (1)协议要相同:HTTP.HTT ...
- 什么是同源策略及解决跨域的三种方式
同源策略 1.1.1 所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个 ip 地址,也非同源.同源策略/SOP(Same origin policy)是一种约 ...
- 跨域的三种主流解决方案
JSONP jsonp实现原理 : 主要是利用动态创建script标签请求后端接口地址,然后传递callback参数,后端接收callback,后端经过数据处理,返回callback函数调用的形式,c ...
- 前端经常遇到的跨域问题几种解决方案
跨域(非同源策略请求) 同源策略请求 ajax/fetch 跨域传输 部署到同一个web服务器上:同源策略 xampp 修改本地的host文件 127.0.0.1:1234 http://api.qq ...
- $.ajax 加了headers报错_Springboot解决Ajax跨域的三种方式
这篇文章不华丽,但比较实用,能解决不少大家实际业务中的问题.大家可以收藏起来,以备用时之需! 1.同源策略 1.1 含义 ajax出现请求跨域错误问题,主要原因就是因为浏览器的"同源策略&q ...
- 跨域的五种解决方案详解
1.跨域解决方案一:cors技术 CORS :全称cross origin resource share (资源共享) 工作原理: 服务器 在返回响应报文的时候,在响应头中 设置一个允许的header ...
最新文章
- java线程stop re_Java 多线程 之 stop停止线程实例
- java对于文件传输时---编码格式的一些设置方法
- 委托、多播委托(MulticastDelegate)
- Linux 查看当前用户id和组id
- win7系统怎么样在计算机里找桌面,如何在64位win7电脑中创建一个“显示桌面”的快捷方式...
- 最简单的视音频播放示例3:Direct3D播放YUV,RGB(通过Surface)
- 大数据风控-提高授信审查效率,做好这7点是关键
- Linux 进程间通信(IPC)---大总结
- OpenCV-Python实战(番外篇)——利用 SVM 算法识别手写数字
- 利用H5开发微信公众号
- 邢台市初中计算机考试,2019年邢台中考总分多少分,邢台中考各个科目多少分
- apache部署mo_python
- JAVA虚拟机环境如何在IMX6平台上搭建呢?
- 计算机运维需要那些知识,运维必知必备!73页计算机基础知识,新手小白也能轻松读懂...
- qt里的pushButton中的clicked(bool);用法
- arduino 步进电机驱动库_Arduino驱动 步进电机
- iframe解决跳转登录界面问题
- 在线网校系统搭建的意义是什么?怎么搭建?
- Last_Error: Slave SQL thread retried transaction 10 time(s) in vain, giving up. Consider raising the
- 用c++输出一个等腰三角形
热门文章
- 游戏中常见动物的象征意义
- 营收净利涨超60%,吉比特凭借《摩尔庄园》赶超完美世界?
- 低辐射玻璃市场现状研究分析与发展前景预测报告
- Java计算机毕业设计大学生家教管理系统源码+系统+数据库+lw文档
- 宫崎骏老爷子的动漫作品
- UOJ#273. 【清华集训2016】你的生命已如风中残烛
- 2021计算机专业笔记本推荐,2021适合学生的笔记本电脑推荐
- GTD 工具 MyLifeOrganized v5.0.1 绿色便携版
- W3C在Web无障碍上的努力
- [转] 不忠不孝不义的男人,最受女纸欢迎