问答
1. 什么是同源策略?
同源定义:所谓同源是指,域名,协议,端口相同。
<pre>例:http://www.x.com/index.html(与以下URL对比) http://www.x.com/reg.html (同源) http://1s.x.com/reg.htm(域名不同,不同源) https://www.x.com/index.htm(协议不同,不同源) http://www.x.com:8080/reg.html (端口不一致,不同源)
</pre>
同源策略:同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。同源策略规定不同源的客户端脚本未经明确授权的情况下,不能读写对方的资源,但是可以引用。
<pre>a.com/index.html 可以引用b.com/main.js 可以引用b.com/style.css 可以引用b.com/logo.bng 但是a.com里面的b.com/main.js不能对b.com的资源进行读写(ajax报错)
</pre>
2. 什么是跨域?跨域有几种实现形式?
跨域:指不同脚本之间的相互访问,由于浏览器同源策略的限制,不同域名下的脚本之间不可以相互读写数据,这种情况下我们就需要用到跨域请求。
跨域的情况:
跨域的形式:
-
降域:
- 定义及作用:在同一主域名下进行降域。通过降域可以使两个一级域名相同,二级域名不同的网页实现跨域资源共享。如child1.a.com和child2.a.com,他们有共同的父域名a.com,同时在当前页面和iframe加上document.domain = a.com进行降域处理。
-
缺点:
- 适用场景有限:它要求两个域名是父子域名的关系,需要在ifame嵌套时有用。
- 安全性低:当子域名被攻击或者恶意注入时,父域名下的信息会被暴露。
-
JSONP
- 原理:通过script方式请求资源,并把回调函数以参数的形式传递给服务端,并在服务端执行回调函数。
-
缺点:
- 安全性问题,任意网站只要通过jsonp方式就可以跨域访问目标域名下的信息,那么如何解决?在跨域请求数据时在参数中加上与目标域名约定好的一个token变量,这样其他网站访问该域名时,目标网站通过辨认这个约定好的信息而决定是否可以被跨域访问。
- 不能用POST方法获取数据,只能用GET方法获取数据。
- callback方法由于是根据用户需求自己实现的,可能会被恶意注入脚本,获取隐私信息。
-
CORS
- 原理:使用"Origin:"请求头和"Access-Control-Allow-Origin"响应头来扩展HTTP。其实就是利用新的HTTP头部来进行浏览器与服务器之间的沟通。
- 缺点:IE浏览器不支持或者部分支持CORS方式
-
postMessage
- postMessge()是HTML5新定义的通信机制。所有主流浏览器都已实现。该API定义在Window对象。该方法可以通过绑定window的message事件来监听发送跨文档消息传输内容。
-
window.name实现的跨域数据传输
- window 对象的name属性是一个很特别的属性,当该window的location变化,然后重新加载,它的name属性可以依然保持不变。那么我们可以在页面 A中用iframe加载其他域的页面B,而页面B中用JavaScript把需要传递的数据赋值给window.name,iframe加载完成之后(iframe.onload),页面A修改iframe的地址,将其变成同域的一个地址,然后就可以读出iframe的window.name的值了(因为A中的window.name和iframe中的window.name互相独立的,所以不能直接在A中获取window.name,而要通过iframe获取其window.name)。这个方式非常适合单向的数据请求,而且协议简单、安全。不会像JSONP那样不做限制地执行外部脚本。
-
location.hash
- 因为父窗口可以对iframe进行URL读写,iframe也可以读写父窗口的URL,URL有一部分被称为hash,就是#号及其后面的字符,它一般用于浏览器锚点定位,Server端并不关心这部分,应该说HTTP请求过程中不会携带hash,所以这部分的修改不会产生HTTP请求,但是会产生浏览器历史记录。此方法的原理就是改变URL的hash部分来进行双向通信。每个window通过改变其他 window的location来发送消息(由于两个页面不在同一个域下IE、Chrome不允许修改parent.location.hash的值,所以要借助于父窗口域名下的一个代理iframe),并通过监听自己的URL的变化来接收消息。这个方式的通信会造成一些不必要的浏览器历史记录,而且有些浏览器不支持onhashchange事件,需要轮询来获知URL的改变,最后,这样做也存在缺点,诸如数据直接暴露在了url中,数据容量和类型都有限等。
3. jsonp 的原理是什么?
原理:因为通过script标签引入的js是不受同源策略的限制的,所以我们可以通过script标签引入一个js或者是一个其他后缀形式(如php,jsp等)的文件,此文件返回一个js函数的调用,如返回JSONP_getUsers(["mike","john","ruby"]),也就是说此文件返回的结果调用了JSONP_getUsers函数,并且把["mike","john","ruby"]传进去,这个["mike","john","ruby"]是一个用户列表。那么如果此时我们的页面中有一个JSONP_getUsers函数,那么JSONP_getUsers就被调用到,并且传入了用户列表。此时就实现了在本域获取其他域数据的功能,也就是跨域。
4. CORS是什么?
CORS 全称是跨域资源共享(Cross-Origin Resource Sharing),它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制,实现原理是服务器在响应头加入Access-Control-Allow-Origin字段,如果发出请求的网站包含在被请求网站的允许名单中,就能实现跨域AJAX请求,它支持现代浏览器,IE支持10以上。
练习
本地搭建服务器,演示同源策略。
- 本地搭建服务器(如果使用 SAE 可创建不同的代码版本,这样可通过1.xxx.sinapp.com和2.xxx.sinapp.com 访问了)
-
修改 本地host,通过不同域名访问本地服务器。比如访问http://a.com/index.html, http://b.com/ajax.php,本质是
-
在 index.html 里使用 ajax 接口访问 http://b.com/ajax.php 里的数据。
-
查看输出报错
-
同个IP不同域名:通过设置hosts文件,对本机127.0.0.1设置多个域名
-
在http://snow.com/task31.html里使用ajax接口访问http://xmz.com/ajax.php。
snow.com/task31.html
ajax请求发送失败,查看输出报错:
至少使用一种方式解决跨域问题
- CORS方式:在xmz.com/ajax.php增加:header('Access-Control-Allow-Origin:http://www.snow.com');如下:
成功获取到了xmz.com/ajax.php的数据,输出结果如下:
- jsonp方式:利用动态的script便签的创建获取到数据
输出结果:
本文版权归本人和饥人谷所有,转载请注明来源。
网友评论