本节内容:实现跨域常用的两种方式 —— 降域 和 postMessage
零:跨域报错展示
在非同源情况下,操作 ifream 引入的元素时,浏览器会阻止这一操作,并且报错如下:
跨域报错 —— ifream
- 本节会做演练,所以首先修改 hosts 文件,本节演练 hosts 文件增添内容为:
127.0.0.1 localhost
127.0.0.1 a.yang.com
127.0.0.1 b.yang.com
127.0.0.1 yang.com
127.0.0.1 a.com
127.0.0.1 b.com
一、降域
-
何为降域?
降域仍是解决跨域问题的一种方案,通过双向设置 document.domain 的值,解决主域名下的跨域问题。
-
降域的原理
-
比如,有两个二级域名:a.yang.com 和 b.yang.com,可通过设定 document.domain 的值为主域名:yang.com 的方式,突破浏览器的同源策略限制,来获取和操作对方的元素
-
这就好比,小 A 和小 B,手里拿着城主的令牌,通过哨卡时才能畅行无阻,否则哨卡不让过
-
这也就决定了,降域具有很大的局限性,适用范围较小,适合在同一主域名下使用;需要有降的空间,方可使用降域方式
-
降域的使用
-
A 页面域为:a.yang.com
-
B 页面域为:b.yang.com
-
A 和 B 两页面都需加入该行代码:
document.domain = 'yang.com';
,‘yang.com 是 a.yang.com 和 b.yang.com 的主域名 -
降域演练
自己动手,丰衣足食。我来手动演练一番。
-
演练说明
1)页面的说明:
A 页面的域为 a.yang.com;A 页面拥有两个元素 input 输入框、ifream,ifream引入 B 页面资源;
B 页面的域为 b.yang.com;B 页面拥有一个元素 input 输入框
2)实现的功能:在任意 input 输入框中输入值时,另外一个 input 输入框同步显示输入的值 -
搭建 web 服务器的工具:server-mock
A 页面代码 a.yang.com
var input = document.querySelector('.main input');
input.addEventListener('input', function () {
console.log('window:' + this.value);
window.frames[0].document.querySelector('input').value = this.value;
});
document.domain = 'yang.com';
var input = document.querySelector('input');
input.addEventListener('input', function () {
console.log('iframe:'+ this.value);
window.parent.document.querySelector('input').value = this.value;
});
document.domain = 'yang.com';
1)同源情况下:window.frames[0].document.querySelector('input') 可取到 ifream 中的 input 元素
2)非同源情况下:因为同源策略的限制,无法取到相应元素,会报错
二、postMessage
因为降域的局限性比较大,只能使用到有降域空间的域名上,那么当两个主域名完全不同时,应该如何处理呢?来看看新方法 postMessage。
-
postMessage 原理
-
postMessage 是 HTML5 中新增方法,可实现跨域通信;
-
postMessage 并不是向服务器读写资源,只是向外发送消息而已;可以把它当做使用手机发送短信消息,仅此而已。
-
也就是:A 页面向 B 页面发送了一条消息,B 页面会接受到该消息,如果 B 页面需要该消息,则监听 message;否则无需关心该消息
-
postMessage 的使用
-
发送方:为目标元素添加事件处理程序,监听事件类型
-
接收方:为 window 添加事件处理程序,事件类型为 messag
-
postMessage 的演练
自己动手,丰衣足食。我来手动演练一番。
-
演练说明
1)页面的说明:
A 页面的域为 a.com;A 页面拥有两个元素 input 输入框、ifream,ifream引入 B 页面资源;
B 页面的域为 b.com;B 页面拥有一个元素 input 输入框
2)实现的功能:在任意 input 输入框中输入值时,另外一个 input 输入框同步显示输入的值 -
搭建 web 服务器的工具:server-mock
A 页面代码 a.com
var input = document.querySelector('.main input');
input.addEventListener('input', function () {
console.log('window:' + this.value);
window.frames[0].postMessage(this.value, '*');
});
window.addEventListener('message', function (e) {
console.log('window:'+ e.data);
input.value = e.data;
})
var input = document.querySelector('input');
input.addEventListener('input', function () {
console.log('iframe:'+ this.value);
window.parent.postMessage(this.value, 'http://a.com:8080');
});
window.addEventListener('message', function (e) {
console.log('ifream:'+ e.data);
input.value = e.data;
})
-
postMessage 的注意点
- 这样就解除了降域的限制,可以将 postMessage 应用到各个不同的域之间,实现跨域访问。该方式比较安全,因为对方并不能直接操控我方资源,仅仅是发了一条消息,相当于指令,而最终操作权限仍在自己手中
- 虽然解决了降域的限制,但是:postMessage 是 window 的一个方法,话句话说:它的弱点是只能向 window 窗口发送消息。所以使用时至少要有一个 window 才行,postMessage 不可以向其他域名发送消息。
最后:降域和 postMessage 都是小众的降域方式,并不是经常使用,若有需求可按需选择
本文章著作权归饥人谷和本人所有,转载须说明来源!
网友评论