什么是浏览器同源策略
同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说 Web 是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
它的核心就在于它认为自任何站点装载的信赖内容是不安全的。当被浏览器半信半疑的脚本运行在沙箱时,它们应该只被允许访问来自同一站点的资源,而不是那些来自其它站点可能怀有恶意的资源。
所谓同源是指:域名、协议、端口相同。
下表是相对于 http://www.laixiangran.cn/home/index.html
的同源检测结果:
另外,同源策略又分为以下两种:
DOM 同源策略:禁止对不同源页面 DOM 进行操作。这里主要场景是 iframe 跨域的情况,不同域名的 iframe 是限制互相访问的。 XMLHttpRequest 同源策略:禁止使用 XHR 对象向不同源的服务器地址发起 HTTP 请求。
为什么要有跨域限制
因为存在浏览器同源策略,所以才会有跨域问题。那么浏览器是出于何种原因会有跨域的限制呢。其实不难想到,跨域限制主要的目的就是为了用户的上网安全。
如果浏览器没有同源策略,会存在什么样的安全问题呢。下面从 DOM 同源策略和 XMLHttpRequest 同源策略来举例说明:
如果没有 DOM 同源策略,也就是说不同域的 iframe 之间可以相互访问,那么黑客可以这样进行攻击:
做一个假网站,里面用 iframe 嵌套一个银行网站 http://mybank.com
。 把 iframe 宽高啥的调整到页面全部,这样用户进来除了域名,别的部分和银行的网站没有任何差别。 这时如果用户输入账号密码,我们的主网站可以跨域访问到 http://mybank.com
的 dom 节点,就可以拿到用户的账户密码了。
如果 XMLHttpRequest 同源策略,那么黑客可以进行 CSRF(跨站请求伪造) 攻击:
用户登录了自己的银行页面 http://mybank.com
,http://mybank.com
向用户的 cookie 中添加用户标识。 用户浏览了恶意页面 http://evil.com
,执行了页面中的恶意 AJAX 请求代码。 http://evil.com
向 http://mybank.com
发起 AJAX HTTP 请求,请求会默认把 http://mybank.com
对应 cookie 也同时发送过去。银行页面从发送的 cookie 中提取用户标识,验证用户无误,response 中返回请求数据。此时数据就泄露了。 而且由于 Ajax 在后台执行,用户无法感知这一过程。
因此,有了浏览器同源策略,我们才能更安全的上网。
不受同源策略限制的
1. 页面中的链接,重定向以及表单提交是不会受到同源策略限制的。
2. 跨域资源的引入是可以的。但是js不能读写加载的内容。如嵌入到页面中的<script src="..."></script>,<img>,<link>,<iframe>等。
跨域的解决方法
从上面我们了解到了浏览器同源策略的作用,也正是有了跨域限制,才使我们能安全的上网。但是在实际中,有时候我们需要突破这样的限制,因此下面将介绍几种跨域的解决方法。
CORS(跨域资源共享)
CORS(Cross-origin resource sharing,跨域资源共享)是一个 W3C 标准,定义了在必须访问跨域资源时,浏览器与服务器应该如何沟通。CORS 背后的基本思想,就是使用自定义的 HTTP 头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。
CORS 需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE 浏览器不能低于 IE10。
整个 CORS 通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS 通信与同源的 AJAX 通信没有差别,代码完全一样。浏览器一旦发现 AJAX 请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现 CORS 通信的关键是服务器。只要服务器实现了 CORS 接口,就可以跨源通信。
浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
只要同时满足以下两大条件,就属于简单请求 。
请求方法是以下三种方法之一:
HTTP的头信息不超出以下几种字段:
Accept Accept-Language Content-Language Last-Event-ID Content-Type:只限于三个值 application/x-www-form-urlencoded、multipart/form-data、text/plain
凡是不同时满足上面两个条件,就属于非简单请求 。
浏览器对这两种请求的处理,是不一样的。
简单请求
在请求中需要附加一个额外的 Origin 头部,其中包含请求页面的源信息(协议、域名和端口),以便服务器根据这个头部信息来决定是否给予响应。例如:Origin: http://www.laixiangran.cn
如果服务器认为这个请求可以接受,就在 Access-Control-Allow-Origin 头部中回发相同的源信息(如果是公共资源,可以回发 * )。例如:Access-Control-Allow-Origin:http://www.laixiangran.cn
没有这个头部或者有这个头部但源信息不匹配,浏览器就会驳回请求。正常情况下,浏览器会处理请求。注意,请求和响应都不包含 cookie 信息。 如果需要包含 cookie 信息,ajax 请求需要设置 xhr 的属性 withCredentials 为 true,服务器需要设置响应头部 Access-Control-Allow-Credentials: true
。
非简单请求
浏览器在发送真正的请求之前,会先发送一个 Preflight 请求给服务器,这种请求使用 OPTIONS 方法,发送下列头部:
Origin:与简单的请求相同。 Access-Control-Request-Method: 请求自身使用的方法。 Access-Control-Request-Headers: (可选)自定义的头部信息,多个头部以逗号分隔。
例如:
Origin: http://www.laixiangran.cn
Access-Control-Request-Method: POST
Access-Control-Request-Headers: NCZ
发送这个请求后,服务器可以决定是否允许这种类型的请求。服务器通过在响应中发送如下头部与浏览器进行沟通:
Access-Control-Allow-Origin:与简单的请求相同。 Access-Control-Allow-Methods: 允许的方法,多个方法以逗号分隔。 Access-Control-Allow-Headers: 允许的头部,多个方法以逗号分隔。 Access-Control-Max-Age: 应该将这个 Preflight 请求缓存多长时间(以秒表示)。
例如:
Access-Control-Allow-Origin: http://www.laixiangran.cn
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: NCZ
Access-Control-Max-Age: 1728000
一旦服务器通过 Preflight 请求允许该请求之后,以后每次浏览器正常的 CORS 请求,就都跟简单请求一样了。
优点
CORS 通信与同源的 AJAX 通信没有差别,代码完全一样,容易维护。 支持所有类型的 HTTP 请求。
缺点
存在兼容性问题,特别是 IE10 以下的浏览器。 第一次发送非简单请求时会多一次请求。
JSONP 跨域
由于 script
标签不受浏览器同源策略的影响,允许跨域引用资源。因此可以通过动态创建 script 标签,然后利用 src 属性进行跨域,这也就是 JSONP 跨域的基本原理。
直接通过下面的例子来说明 JSONP 实现跨域的流程:
function handleResponse (data ) {
console .log(data);
};
var body = document .getElementsByTagName(‘body’ )[0 ]; var script = document .gerElement(‘script’ ); script.src = ‘http://www.laixiangran.cn/json?callback=handleResponse’ ; body.appendChild(script);
优点
使用简便,没有兼容性问题,目前最流行的一种跨域方法。
缺点
只支持 GET 请求。 由于是从其它域中加载代码执行,因此如果其他域不安全,很可能会在响应中夹带一些恶意代码。 要确定 JSONP 请求是否失败并不容易。虽然 HTML5 给 script 标签新增了一个 onerror 事件处理程序,但是存在兼容性问题。
jsonp原理解析
举个例子:
下表给出了相对http://a.xyz.com/dir/page.html同源检测的示例:
URL 结果 原因 http://a.xyz.com/dir2/other.html
成功 http://a.xyz.com/dir/inner/another.html
成功 https://a.xyz.com/secure.html
失败 不同协议 ( https和http ) http://a.xyz.com:81/dir/etc.html
失败 不同端口 ( 81和80) http://a.opq.com/dir/other.html
失败 不同域名 ( xyz和opq)
同源策略是什么
同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。所以xyz.com下的js脚本采用ajax读取abc.com里面的文件数据是会被拒绝的。
同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
不受同源策略限制的
1. 页面中的链接,重定向以及表单提交是不会受到同源策略限制的。
2. 跨域资源的引入是可以的。但是js不能读写加载的内容。如嵌入到页面中的<script src="..."></script>,<img>,<link>,<iframe>等。
举个例子
我们手写两个Django demo:
demo1
urls.py
urlpatterns = [
url( r'^abc/' , views. abc) ,
]
views.py
def abc ( request) :
return HttpResponse( "rion" )
demo2
urls.py
urlpatterns = [
url( r'^xyz/' , views. xyz) ,
]
views.py
def xyz ( request) :
return render( request, "xyz.html" )
xyz.html
< ! DOCTYPE HTML>
< html>
< head>
< meta charset= "UTF-8" >
< meta http-equiv= "x-ua-compatible" content= "IE=edge" >
< meta name= "viewport" content= "width=device-width, initial-scale=1" >
< title> xyz< /title>
< /head>
< body>
< button id= "b1" > 点我< /button>
< script src= "https://cdn.bootcss.com/jquery/3.3.1/jquery.js" > < /script>
< script>
$( "#b1" ) .click( function ( ) {
$.ajax( {
url: "http://127.0.0.1:8002/abc/" ,
type: "get" ,
success:function ( res) {
console.log( res) ;
}
} )
} ) ;
< /script>
< /body>
< /html>
现在,打开使用浏览器打开http://127.0.0.1:8000/xyz/,点击页面上的 '点我' 按钮,会在console页面发现错误信息如下:
为什么报错呢?因为同源策略限制跨域发送ajax请求。
细心点的同学应该会发现我们的demo1项目其实已经接收到了请求并返回了响应,是浏览器对非同源请求返回的结果做了拦截。
再细心点的同学会发现,我们使用cdn方式引用的jQuery文件也是跨域的,它就可以使用。
同样是从其他的站点拿东西,script标签就可以。那我们能不能利用这一点搞点事情呢?
把xyz.html中的代码改一下:
< ! DOCTYPE HTML>
< html>
< head>
< meta charset= "UTF-8" >
< meta http-equiv= "x-ua-compatible" content= "IE=edge" >
< meta name= "viewport" content= "width=device-width, initial-scale=1" >
< title> xyz< /title>
< /head>
< body>
< button id= "b1" > 点我< /button>
< script src= "https://cdn.bootcss.com/jquery/3.3.1/jquery.js" > < /script>
< script src= "http://127.0.0.1:8002/abc/" > < /script>
< /body>
< /html>
现在,我们刷新一下页面,会出现如下错误提示:
看来后端返回的响应已经被拿到了,只不过把rion当成了一个变量来使用,但是该页面上却没有定义一个名为rion的变量。所以出错了。
那我定义一个rion变量还不行吗?
< ! DOCTYPE HTML>
< html>
< head>
< meta charset= "UTF-8" >
< meta http-equiv= "x-ua-compatible" content= "IE=edge" >
< meta name= "viewport" content= "width=device-width, initial-scale=1" >
< title> xyz< /title>
< /head>
< body>
< button id= "b1" > 点我< /button>
< script src= "https://cdn.bootcss.com/jquery/3.3.1/jquery.js" > < /script>
< script>
var rion = 100;
< /script>
< script src= "http://127.0.0.1:8002/abc/" > < /script>
< /body>
< /html>
这次就不会报错了。
我定义一个变量可以,那可不可以定义一个函数呢?
< ! DOCTYPE HTML>
< html>
< head>
< meta charset= "UTF-8" >
< meta http-equiv= "x-ua-compatible" content= "IE=edge" >
< meta name= "viewport" content= "width=device-width, initial-scale=1" >
< title> xyz< /title>
< /head>
< body>
< button id= "b1" > 点我< /button>
< script src= "https://cdn.bootcss.com/jquery/3.3.1/jquery.js" > < /script>
< script>
function rion( ) {
console.log( "选我不后悔!" ) ;
}
< /script>
< script src= "http://127.0.0.1:8002/abc/" > < /script>
< /body>
< /html>
同时把返回的响应也改一下:
def abc ( request) :
return HttpResponse( "rion()" )
此时,再次刷新页面,可以看到下面的结果。
啊,真是让人性兴奋的操作!
我返回的 rion(),页面上拿到这个响应之后直接执行了rion函数!
那函数中可不可以传递参数呢?我们试一下!
demo2中的xyz.html
< ! DOCTYPE HTML>
< html>
< head>
< meta charset= "UTF-8" >
< meta http-equiv= "x-ua-compatible" content= "IE=edge" >
< meta name= "viewport" content= "width=device-width, initial-scale=1" >
< title> xyz< /title>
< /head>
< body>
< button id= "b1" > 点我< /button>
< script src= "https://cdn.bootcss.com/jquery/3.3.1/jquery.js" > < /script>
< script>
function rion( res) {
console.log( res) ;
}
< /script>
< script src= "http://127.0.0.1:8002/abc/" > < /script>
< /body>
< /html>
demo1中的视图函数:
def abc ( request) :
res = { "code" : 0 , "data" : [ "SNIS-561" , "SNIS-517" , "SNIS-539" ] }
return HttpResponse( "rion({})" . format ( json. dumps( res) ) )
刷新页面查看效果:
果然传递参数也是可以的!
我们通过script标签的跨域特性来绕过同源策略拿到想要的数据了!!!
这其实就是JSONP的简单实现模式,或者说是JSONP的原型:创建一个回调函数,然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调。
将JSON数据填充进回调函数,这就是JSONP的JSON+Padding的含义。
但是我们更多时候是希望通过事件触发数据的获取,而不是像上面一样页面一刷新就执行了,这样很不灵活。
其实这很好解决,我们可以通过javascript动态的创建script标签来实现。
demo2中的xyz.html
< ! DOCTYPE HTML>
< html>
< head>
< meta charset= "UTF-8" >
< meta http-equiv= "x-ua-compatible" content= "IE=edge" >
< meta name= "viewport" content= "width=device-width, initial-scale=1" >
< title> xyz< /title>
< /head>
< body>
< button id= "b1" > 点我< /button>
< script src= "https://cdn.bootcss.com/jquery/3.3.1/jquery.js" > < /script>
< script>
function rion( res) {
console.log( res) ;
}
function addScriptTag( src) {
var scriptEle = document.createElement( "script" ) ;
$( scriptEle) .attr( "src" , src) ;
$( "body" ) .append( scriptEle) ;
$( scriptEle) .remove( ) ;
}
$( "#b1" ) .click( function ( ) {
addScriptTag( "http://127.0.0.1:8002/abc/" )
} )
< /script>
< /body>
< /html>
这样当我们点击b1按钮的时候,会在页面上插入一个script标签,然后从后端获取数据。
为了实现更加灵活的调用,我们可以把客户端定义的回调函数的函数名传给服务端,服务端则会返回以该回调函数名,将获取的json数据传入这个函数完成回调。
demo2中的xyz.html
< ! DOCTYPE HTML>
< html>
< head>
< meta charset= "UTF-8" >
< meta http-equiv= "x-ua-compatible" content= "IE=edge" >
< meta name= "viewport" content= "width=device-width, initial-scale=1" >
< title> xyz< /title>
< /head>
< body>
< button id= "b1" > 点我< /button>
< script src= "https://cdn.bootcss.com/jquery/3.3.1/jquery.js" > < /script>
< script>
function rion( res) {
console.log( res) ;
}
function addScriptTag( src) {
var scriptEle = document.createElement( “script”) ;
$( scriptEle) .attr( “src”, src) ;
$( “body”) .append( scriptEle) ;
$( scriptEle) .remove( ) ;
}
$( "#b1" ) .click( function ( ) {
addScriptTag( “http://127.0.0.1:8002/abc/?callback= rion”)
} ) ;
< /script>
< /body>
< /html>
demo1中的views.py
def abc ( request) :
res = { "code" : 0 , "data" : [ "SNIS-561" , "SNIS-517" , "SNIS-539" ] }
func = request. GET. get( "callback" )
return HttpResponse( "{}({})" . format ( func, json. dumps( res) ) )
这样就能实现动态的调用了。
jQuery中getJSON方法
jQuery中有专门的方法实现jsonp。
demo2中的xyz.html
< ! DOCTYPE HTML>
< html>
< head>
< meta charset= "UTF-8" >
< meta http-equiv= "x-ua-compatible" content= "IE=edge" >
< meta name= "viewport" content= "width=device-width, initial-scale=1" >
< title> xyz< /title>
< /head>
< body>
< button id= "b1" > 点我< /button>
< script src= "https://cdn.bootcss.com/jquery/3.3.1/jquery.js" > < /script>
< script>
$( "#b1" ) .click( function ( ) {
$.getJSON( "http://127.0.0.1:8002/abc/?callback=?" , function ( res) {
console.log( res) ;
} )
} ) ;
< /script>
< /body>
< /html>
要注意的是在url的后面必须要有一个callback参数,这样getJSON方法才会知道是用JSONP方式去访问服务,callback后面的那个?是jQuery内部自动生成的一个回调函数名。
但是如果我们想自己指定回调函数名,或者说服务上规定了回调函数名该怎么办呢?我们可以使用$.ajax方法来实现:
< ! DOCTYPE HTML>
< html>
< head>
< meta charset= "UTF-8" >
< meta http-equiv= "x-ua-compatible" content= "IE=edge" >
< meta name= "viewport" content= "width=device-width, initial-scale=1" >
< title> xyz< /title>
< /head>
< body>
< button id= "b1" > 点我< /button>
< script src= "https://cdn.bootcss.com/jquery/3.3.1/jquery.js" > < /script>
< script>
$( "#b1" ) .click( function ( ) {
$.ajax( {
url: "http://127.0.0.1:8002/abc/" ,
dataType: "jsonp" ,
jsonp: "callback" ,
jsonpCallback: "rion2"
} )
} ) ;
function rion2( res) {
console.log( res) ;
}
< /script>
< /body>
< /html>
不过我们通常都会将回调函数写在success回调中:
< ! DOCTYPE HTML>
< html>
< head>
< meta charset= "UTF-8" >
< meta http-equiv= "x-ua-compatible" content= "IE=edge" >
< meta name= "viewport" content= "width=device-width, initial-scale=1" >
< title> xyz< /title>
< /head>
< body>
< button id= "b1" > 点我< /button>
< script src= "https://cdn.bootcss.com/jquery/3.3.1/jquery.js" > < /script>
< script>
$( "#b1" ) .click( function ( ) {
$.ajax( {
url: "http://127.0.0.1:8002/abc/" ,
dataType: "jsonp" ,
success: function ( res) {
console.log( res) ;
}
} )
} )
< /script>
< /body>
< /html>
图像 Ping 跨域
由于 img
标签不受浏览器同源策略的影响,允许跨域引用资源。因此可以通过 img 标签的 src 属性进行跨域,这也就是图像 Ping 跨域的基本原理。
直接通过下面的例子来说明图像 Ping 实现跨域的流程:
var img = new Image();
img.onload = img.onerror = function ( ) { console .log(“Done!” ); }
img.src = ‘http://www.laixiangran.cn/test?name=laixiangran’ ;
优点
用于实现跟踪用户点击页面或动态广告曝光次数有较大的优势。
缺点
只支持 GET 请求。 只能浏览器与服务器的单向通信,因为浏览器不能访问服务器的响应文本。
服务器代理
浏览器有跨域限制,但是服务器不存在跨域问题,所以可以由服务器请求所要域的资源再返回给客户端。
服务器代理是万能的。
document.domain 跨域
对于主域名相同,而子域名不同的情况,可以使用 document.domain 来跨域。这种方式非常适用于 iframe 跨域的情况。
比如,有一个页面,它的地址是 http://www.laixiangran.cn/a.html
,在这个页面里面有一个 iframe,它的 src 是 http://laixiangran.cn/b.html
。很显然,这个页面与它里面的 iframe 框架是不同域的,所以我们是无法通过在页面中书写 js 代码来获取 iframe 中的东西的。
这个时候,document.domain 就可以派上用场了,我们只要把 http://www.laixiangran.cn/a.html
和 http://laixiangran.cn/b.html
这两个页面的 document.domain 都设成相同的域名就可以了。但要注意的是,document.domain 的设置是有限制的,我们只能把 document.domain 设置成自身或更高一级的父域,且主域必须相同。例如:a.b.laixiangran.cn
中某个文档的 document.domain 可以设成 a.b.laixiangran.cn
、b.laixiangran.cn
、laixiangran.cn
中的任意一个,但是不可以设成 c.a.b.laixiangran.cn
,因为这是当前域的子域,也不可以设成 baidu.com
,因为主域已经不相同了。
例如,在页面 http://www.laixiangran.cn/a.html
中设置document.domain:
<iframe src ="http://laixiangran.cn/b.html" id ="myIframe" onload ="test()" >
<script >
document .domain = 'laixiangran.cn' ;
function test ( ) {
console .log(document .getElementById('myIframe' ).contentWindow);
}
</script >
在页面 http://laixiangran.cn/b.html
中也设置 document.domain,而且这也是必须的,虽然这个文档的 domain 就是 laixiangran.cn
,但是还是必须显式地设置 document.domain 的值:
<script >
document .domain = 'laixiangran.cn' ;
</script >
这样,http://www.laixiangran.cn/a.html
就可以通过 js 访问到 http://laixiangran.cn/b.html
中的各种属性和对象了。
window.name 跨域
window 对象有个 name 属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面(不管是相同域的页面还是不同域的页面)都是共享一个 window.name
的,每个页面对 window.name
都有读写的权限,window.name
是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。
通过下面的例子介绍如何通过 window.name 来跨域获取数据的。
页面 http://www.laixiangran.cn/a.html
的代码:
< iframe src= "http://laixiangran.cn/b.html" id= "myIframe" onload= "test()" style= "display: none;" >
< script>
// 2. iframe载入 "http://laixiangran.cn/b.html 页面后会执行该函数
function test( ) {
var iframe = document.getElementById( 'myIframe' ) ;
// 重置 iframe 的 onload 事件程序,
// 此时经过后面代码重置 src 之后,
// http://www.laixiangran.cn/a.html 页面与该 iframe 在同一个源了,可以相互访问了
iframe.onload = function( ) {
var data = iframe.contentWindow.name; // 4. 获取 iframe 里的 window.name
console.log( data) ; // hello world!
} ;
// 3. 重置一个与 http://www.laixiangran.cn/a.html 页面同源的页面
iframe.src = 'http://www.laixiangran.cn/c.html' ;
}
< /script>
页面 http://laixiangran.cn/b.html
的代码:
<script type ="text/javascript" >
window .name = "hello world!" ;
</script >
location.hash 跨域
location.hash 方式跨域,是子框架具有修改父框架 src 的 hash 值,通过这个属性进行传递数据,且更改 hash 值,页面不会刷新。但是传递的数据的字节数是有限的。
页面 http://www.laixiangran.cn/a.html
的代码:
<iframe src ="http://laixiangran.cn/b.html" id ="myIframe" onload ="test()" style ="display: none;" >
<script >
function test ( ) {
var data = window .location.hash;
console .log(data);
}
</script >
页面 http://laixiangran.cn/b.html
的代码:
<script type ="text/javascript" >
parent.location.hash = "world" ;
</script >
postMessage 跨域
window.postMessage(message,targetOrigin) 方法是 HTML5 新引进的特性,可以使用它来向其它的 window 对象发送消息,无论这个 window 对象是属于同源或不同源。这个应该就是以后解决 dom 跨域通用方法了。
调用 postMessage 方法的 window 对象是指要接收消息的那一个 window 对象,该方法的第一个参数 message 为要发送的消息,类型只能为字符串;第二个参数 targetOrigin 用来限定接收消息的那个 window 对象所在的域,如果不想限定域,可以使用通配符 *。
需要接收消息的 window 对象,可是通过监听自身的 message 事件来获取传过来的消息,消息内容储存在该事件对象的 data 属性中。
页面 http://www.laixiangran.cn/a.html
的代码:
<iframe src ="http://laixiangran.cn/b.html" id ="myIframe" onload ="test()" style ="display: none;" >
<script >
function test ( ) {
var iframe = document .getElementById('myIframe' );
var win = iframe.contentWindow;
win.postMessage('我是来自 http://www.laixiangran.cn/a.html 页面的消息' , '*' );
}
</script >
页面 http://laixiangran.cn/b.html
的代码:
<script type ="text/javascript" >
window .onmessage = function (e ) {
e = e || event;
console .log(e.data);
}
</script >
参考资料