这个系列,俺将跟大家一起总结总结前端中常见的面试题。
本文,俺将介绍如何解决跨域。
什么是跨域
首先,需要解释的是同源策略,因为跨域就是由同源策略引起的。
同源策略:protocol、port和host都相同的话,则两个URL是同源。
为什么需要同源策略?
阻隔恶意文档,减少可能被攻击的媒介 。
IE中的特殊情况
- 授信范围(Trust Zones):两个相互之间高度互信的域名,如公司域名(corporate domains),则不受同源策略限制。
- 端口:IE 未将端口号纳入到同源策略的检查中,因此 https://company.com:81/index.html 和 https://company.com/index.html 属于同源并且不受任何限制。
前后端通信方式
常见的前后端通信方式有如下几种:
- Ajax (缺点:不支持跨域)
- WebSocket (支持跨域)
- CORS:不受同源策略的限制,支持跨域。一种新的通信协议标准。可以理解成是:同时支持同源和跨域的Ajax。
解决跨域的几种方式
- JSONP
- WebSocket
- CORS (支持所有类型HTTP请求)
- Hash
- postMessage
JSONP
只支持get请求,兼容性不错。
JSONP的原理:通过script标签不跨域的性质。
实现方式如下:
//客户端
<script src="http://www.pipipi.net/?data=name&callback=myjsonp"></script>
//服务端跨域这样写
myjsonp({data:{}})
这样我们就可以在客户端全局创建一个myjsonp函数,用来接收服务端传递的数据。
WebSocket
注意WebSocket中的onclose回调,我们可以进行重连。
CORS
CORS为什么支持跨域的通信?
跨域的时候,浏览器会拦截Ajax的请求,并在http头中加Origin。
Hash
Hash是什么? url的#后面的内容就叫Hash。
跨域原理:Hash的改变,页面不会刷新。
//实现伪代码
//B嵌套在A页面中,A想给B发消息。
//伪代码
var B = document.getElementsByTagName('iframe');
B.src = B.src + '#' + 'jsonString'; //我们可以把JS 对象,通过 JSON.stringify()方法转成 json字符串,发给 B
//然后在B页面中
// B中的伪代码
window.onhashchange = function () { //通过onhashchange方法监听,url中的 hash 是否发生变化
var data = window.location.hash;
};
postMessage
场景:窗口 A (http:A.com
)向跨域的窗口 B (http:B.com
)发送信息
(1)在A窗口中操作如下:向B窗口发送数据:
// 窗口A(http:A.com)向跨域的窗口B(http:B.com)发送信息
Bwindow.postMessage('data', 'http://B.com'); //这里强调的是B窗口里的window对象
(2)在B窗口中操作如下:
// 在窗口B中监听 message 事件
Awindow.addEventListener('message', function (event) { //这里强调的是A窗口里的window对象
console.log(event.origin); //获取 :url。这里指:http://A.com
console.log(event.source); //获取:A window对象
console.log(event.data); //获取传过来的数据
}, false);