既然要突破同源策略,那就要知道什么是同源策略,要不然突破什么呢?
首先看看一个完整的URL的结构
同源策略是指:
- 协议(http或者https);
- 域名(路径可以不相同);
- 端口(port,一般http都是80,https:443)
并且以上三者都需要相同,才被人为是同源;
同源策略目的:
不同源的客户端脚本(javascript)在没明确授权的情况下,不能
读写
非同源的资源;
想象一下,你刚在电影网站上买了票,网银转账,再去浏览别的网站,别的网站读取你的cookie怎么办?并且我还可以调用你网站的脚本,来获取用户信息以及别的信息;所以同源策略是必须的,要不然所有人的信息就是公共财产了;
限制范围:随着互联网的发展,越来越严格的同源策略,使得下面的行为,如果在非同源受到限制:
- DOM无法获取
- AJAX请求不能发送
- Cookie、LocalStorage及IndexDB 无法读取
导致有时候,我们需要用到这些行为,但是又被限制影响了,那么就有如何去突破同源了
1.降域
对于主域相同子域不同(http://www.a.com/ ,http://child.a.com)的情况,在双方域名下 html 文件(index1.html,index2.html) 中都添加一句
document.domain = a.com
,将域名都设置成a.com
,然后在index1.html中创建一个iframe
,然后index1.html的JS就能够读取index2.html的数据了,虽然域名可以向上/下改,但是改完了之后又想改回去就不行;
降域的缺点:只对相同的后缀起作用,也就是主域相同的不同子域;只针对iframe形式的跨域;
2.JSONP(json with padding)
这里自己写了一个DEMO
基本思路就是:
- 网页动态的添加一个
<script>
元素,虽然同源策略不允许跨域Ajax
,但是引用是可以的,于是乎web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件(一般以JSON为后缀),JSONP一个要点就是允许用户传递一个callback参数
给服务端,然后服务端返回数据时会将这个callback参数
作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了; - 概括一下就是:
b.com
把数据放在其域名下的JS(或者php)中,a.com
再把它引用过来,这个引用过来的JS自动执行的时候,就会带着b.com
的数据执行a.com
下的回调函数;
缺点:
1.callback可能被注入,这个可以用字符串过滤解决;
2.安全性问题,当别人拷贝你的代码后,JSONP能被别的站引用,这里需要另一套token机制来保证,使得a与c之间的通讯,需要a的cookie来验证,就算b网拷贝了a的代码,JSONP也不会被b读取;
3.不能使用post只能使用get;
3.CORS(Cross-Origin Resource Sharing)
由于自己刚刚接触,只是用到了简单请求,浏览器在跨域请求的时候,在后端的php里面加上一个 header("Access-Control-Allow-Origin:http://a.com.html");,这样http://a.com.html域名下的AJAX
就可以通过加的这个响应头被允许跨域请求了
这里自己写了一个DEMO
- 简单概括一下:
b.com
声明允许a.com
来访问我,然后a.com
的Js可以正式的发起对b.com
的AJAX - CORS与JSONP的使用目的相同,但是比JSONP更强大;JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。
4.HTML5 postMessage
当要多窗口之间消息传递时,html5引入的message的API可以更方便、有效、安全的解决这些难题。postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。
5.window.name:
利用window.name
只随tab的关系,不随域名跳转的改变而改变,那么就利用a.com
中的iframe
向b.com
中跳转的同时,传入一个参数,b.com
中的函数接收这个参数,在b.com
自己域名下获取数据之后,将数据放在window.name
上,再跳转回a.com
域名下,此时再去获取处理window.name
里面的数据,就达到了效果