跨域的二三事

公司的桌面版运用了 iframe 在取数据方面遇到不少坑,周末空闲把知识点整理下。

什么是跨域

JavaScript对安全访问因素的考虑,是不允许js跨域调用其他页面,具体分为以下几类:

解决方案

  • JSONP

JSONP 和 JSONP?
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。
JSONP是JSON with Padding的略称。它是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)–百度
实际是利用了 <script> 标签的 src 属性并不被同源策略所约束,其实所有的 src 属性的标签都是不被同源策略所约束。

1
2
3
4
5
6
7
8
9
10
11
// html
<script type="text/javascript" src="http://127.0.0.1:20002/test.js"></script>


// test.js 内容
<script type="text/javascript">
//回调函数
function callback(data) {
alert(data.message);
}
</script>

这种方案需要注意的是他支持GET这一种HTTP请求类型,还有就是其他域要有一定可靠性。

  • 跨域资源共享(CORS-Cross Origin Resource Sharing)

CORS 它是JSONP模式的现代升级版,CORS 定义一种跨域访问的机制,可以让AJAX实现跨域访问。CORS 允许一个域上的网络应用向另一个域提交跨域 AJAX 请求与JSONP不同的是,CORS除了GET要求方法以外也支持其他的 HTTP要求。浏览器CORS请求分成两种。

  1. 请求方式
    GET
    HEAD
    POST
  2. HTTP的头信息子段
    Accept
    Accept-Language
    Content-Language
    Last-Event-ID
    Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain,其中’text/plain’默认支持,其他两种则需要预检请求和服务器协商。

满足以上两大点的即为简单请求,否则为非简单请求
注:个人认为除了 cors 之外的跨域解决方案 都是耍流氓

  • document.domain + iframe(适用于跨子域的交互)

只需要在A.htm与B.htm里都加上一句document.domain = ‘xxx.com’,两个页面就有了互信的基础,而能无碍的交互。

  • window.name + iframe

类似在 a 页面(a.com/app.html)中创建一个iframe,把其src指向 b 页面(b.com/data.html),数据页面会把数据附加到这个iframe的window.name上。

  • HTML5中的postMessage(适用于两个iframe或两个页面之间)

postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。
eg:

1
2
3
window.onload=function(){
window.frames[0].postMessage('ok','http://baidu.com');
}

postMessage(data,origin)方法接受两个参数:

  1. data 要传递的数据,html5 规范中提到该参数可以是 JavaScript 的任意基本类型或可复制的对象,但是为了兼容性在传递参数的时候需要使用 JSON.stringify() 方法对对象参数序列化。

  2. origin 字符串参数,指明目标窗口的源,协议+主机+端口号[+URL],URL会被忽略,只会将message传递给指定窗口.