同源策略有两个限制:(1)不能通过ajax去请求不同源中的数据(2)浏览器中不同域的框架之间不能进行js交互
这些限制一定程度上保证了web通信的安全性,但也带来了诸多不便,所以有时候我们需要使用一些跨域方法来获取其他域中的数据。
首先有必要知道什么情况下需要跨域,域名、端口和协议三者只要有一个不相同时,就需要跨域,其中域名包括主域和子域。
我总结了以下8种跨域的方法,前五种是只能单向通信,后三种可以实现双向通信。
- CORS
这个是W3C出的一个标准,它允许浏览器向跨域服务器发送XMLHttpRequest请求,但是否成功取决于服务器。大部分浏览器都已经支持CORS了。
使用CORS来跨域和普通的AJAX对前端来说没什么区别,不需要做什么额外的事,只是请求和响应头部会有一些关于跨域的信息。
2.jsonp
json+padding
原理:浏览器请求script资源时不受同源策略的限制,并且请求到后是立即执行的。
做法:声明一个全局函数,然后动态创建一个script标签,src属性是请求资源地址+获取函数的字段名+函数名,服务器收到后,返回一段js代码,给上面那个函数传入参数,并执行,通常参数就是请求的数据。
优点:不受浏览器兼容性的限制。
缺点:只能发送GET请求。需要服务器端和客户端提前规定好。
3.CSST,利用css跨域传输文本
优点:比JSONP更安全,不需要执行跨站脚本
缺点:只有支持CSS的浏览器才能执行
原理:跟JSONP有些类似,利用css没有同源限制,请求css,设置其content属性为请求内容即可。
4.图像Ping
原理和jsonP,CSST类似,利用图像没有同源限制,请求图像,图像Ping多用于跟踪用户点击页面或动态广告曝光次数。
5.通过window.name跨域
window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,为了安全起见它是以字符串的格式传递信息的,容量高达2M,他的使用方法是这样: 首先将要传送的信息复制给window.name属性,然后再这个窗口下打开另一个页面,最后在第二个页面中读取window.name的值,得到第一个页面发送的信息。
6.设置document.domain
页面框架之间,也就是frame和iframe之间是可以获取彼此的window对象的,但是不可以获取window的属性和方法,只有一个html5新引入的方法例外,这个稍后再说
但是如果两者的document.domain一样的话,就可以获取别的页面的属性和文件了,但domian的设置也是有限制的,所以这个方法也有一定限制性
7.window.postMessage方法
也是用于不同frame间的通信,一个frame调用postMessage方法,传入两个参数,第一个是要发送的消息,第二个是接受消息的window所在的域。接受消息的窗口监听message事件即可
8.websocket
websocket可以在一个单独的持久链接上提供全双工的双向通信,它没有同源限制,所以在需要双向通信时websocket是一个比较不错的跨域选择。
var ws = new WebSocket("http://aa.com/server.php");
ws.onmessage = function(event){
var data = event.data;
//处理
};
var message = {
time: 10,
content: "我是Claiyre"
};
//发送JSON格式的数据
ws.send(JSON.stringify(message));
ws.onclose = function(event){
event.wasClean //布尔值,表示链接是否已经明确地关闭
event.code //状态码
event.reason //原因短语
}
ws.close(); //调用后ws.readyState的值变为2(正在关闭)