跨域问题实践总结!下( [HTML5] postMessage+服务器端(反向代理服务器+CORS Cross-Origin Resource Sharing))

 

4. [HTML5] postMessage

问题:javascript

对于跨域问题,研究了一下html5的postMessage,写了代码测试了一下,感受html5新功能就是好用啊。
此文仅使用html5的新特性postMessage,演示其执行过程和效果:html

方法解释:
postMessage()方法容许来自不一样源的脚本采用异步方式进行有限的通讯,能够实现跨文本档、多窗口、跨域消息传递。
postMessage(data,origin)方法接受两个参数:
1.data:你须要传递的消息,消息传递的格式有必定要求:参数能够是JavaScript的任意基本类型或可复制的对象,然而并非全部浏览器都作到了这点儿,部分浏览器只能处理字符串参数,因此建议直接传递string类型参数。json格式使用JSON.stringify()方法对对象参数序列化,在低版本IE中引用json2.js能够实现相似效果。
2.origin:该参数指明目标窗口的源。postMessage()方法只会将message传递给指定窗口,也能够设置为"*",表示能够传递给任意窗口。html5

原理:java

1.个人页面是parent.html,接收我发送的消息并按照要求返回消息的页面是child.html;git

2.两个页面放在同一个文件夹内;github

3.parent.html发送postMessage消息给child.html,child.html收到消息后经过source.postMessage返回所需信息!apache

 

具体过程以下:json

个人页面是parent.html:api

复制代码
<html>
<div>
    <iframe id="child" src="./child.html"></iframe>
</div>
<script type="text/javascript">
    window.addEventListener('message',function(e){
        alert("msg from child:" + e.data);
    });
    window.onload=function(){//页面加载完即向iframe发送消息
        //var tmp = document.getElementById("child");
        //tmp.postMessage('hello babi','*');  //此处tmp没有postMessage方法,类型错误。
        //alert(tmp); //这是object HTMLIFrameElement类型
        //alert(window.frames[0]);  //这是object Window类型
        //以上方式不可行,只有window类型才能调用postMessage方法!
        window.frames[0].postMessage('hello babi','*');
    }
</script>
</html>
复制代码

中间的文字全都来自child.html!跨域

 

咱们看看接收消息页面child.html:

parent页面向child页面发送了消息,那么在child页面上如何接收消息呢,监听window的message事件就能够

复制代码
<html>
<p id="ll1">I'm child</p>
<p id="ll2">I'm child</p>
<p id="ll3">I'm child</p>
<p id="ll4">I'm child</p>
<script type="text/javascript">
    window.addEventListener('message',function(e){//接收信息后返回信息!
        alert("msg from parent:" + e.data);
        e.source.postMessage('Hello papi', "*");
    });
</script>
</html>
复制代码

这样咱们就能够接收任何窗口传递来的消息了!

咱们运行一下:

这样就实现了跨域、跨窗口消息传递

服务器端的跨域方法

1、反向代理服务器

基础思想很简单,将你的服务器配置成 须要跨域获取的资源的 反向代理服务器。

也就是说,将其余域名的资源映射到你本身的域名之下,这样浏览器就认为他们是同源的。

用你们钟爱的 Apache2 来举个例子:

首先启用两个模块 proxy 和 proxy_http 来开启代理功能:

sudo a2enmod proxy
sudo a2enmod proxy_http

而后在配置文件里面写入:

ProxyPass "/foo" "http://foo.example.com/bar" ProxyPassReverse "/foo" "http://foo.example.com/bar"
  • ProxyPass: 远程服务器在本地服务器的映射。(上面的例子将 http://foo.example.com/bar 映射为 /foo

  • ProxyPassReverse: 配置 Apache2 在 HTTP 跳转时调整 LocationContent-Location 和 URI headers 的值,防止反向代理被绕开。

重启 Apache2:

sudo service apache2 restart

大功告成,这样咱们请求 /foo 就会获得 http://foo.example.com/bar 的内容了。

这种方法其实不太经常使用,机智的读者就会发现,每个资源都要到本身的服务器配置,每次配置都还要重启。

2、CORS

Cross-Origin Resource Sharing 是 W3C 推出的一种跨站资源获取的机制。

首先咱们来看一下浏览器的支持状况:

Chrome Firefox (Gecko) Internet Explorer Opera Safari
4 3.5 8 & 9(XDomainRequest), 10 12 4

移动端的浏览器对这种方法的支持比较完善。如今咱们看到了,若是不须要兼容 IE六、7的话,就可使用这种方法。


这种跨域方案主要的思想是:服务器 在响应头中设置相应的选项,浏览器若是支持这种方法的话就会将这种跨站资源请求视为合法,进而获取资源。

能够设置的响应头信息:

Access-Control-Allow-Origin

Access-Control-Allow-Origin: <origin> | *

origin: 被容许跨域访问这个资源的网站,* 表明所有网站。浏览器会检测这个参数,若是符合要求,才会去获取资源。

举个例子,容许 http://jasonkid.github.io/fezone 来跨域访问这个资源:

Access-Control-Allow-Origin: http://jasonkid.github.io/fezone

Access-Control-Allow-Credentials

Access-Control-Allow-Credentials: true | false

表示是否容许浏览器携带 Cookie 来访问这个资源。
这个属性要和 XMLHttpRequest 的 withCredentials 属性来配合使用。

var xhr = new XMLHttpRequest(); var url = 'http://foo.other/resources/credentialed-content/'; if(xhr) { xhr.open('GET', url, true); xhr.withCredentials = true; // 设置带有 Cookie 的资源请求 xhr.onreadystatechange = handler; xhr.send(); }

可以成功使用带有 Cookie 的资源请求须要知足如下几个条件:

  • XMLHttpRequest 对象中指定了 withCredentials = true

  • 服务器响应头中 Access-Control-Allow-Credentials: true

  • 服务器响应头中 Access-Control-Allow-Origin 不能为 *


如下选项主要是安全性配置的问题,主要是服务器的配置问题了,就不展开介绍了:

  • Access-Control-Expose-Headers

  • Access-Control-Allow-Methods

  • Access-Control-Allow-Headers

相关文章
相关标签/搜索