跨域
- 指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。
- 例如:a页面想获取b页面资源,如果a、b页面的协议、域名、端口、子域名不同,所进行的访问行动都是跨域的,而浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源。注意:跨域限制访问,其实是浏览器的限制。
- 特别注意:不同源的页面之间,不准相互访问数据
同源策略
同源定义
- 源
window.origin或location.origin 可以得到当前源 - 源 = 协议 + 域名 + 端口号
如果两个URL的
- 协议
- 域名
- 端口号
- 完全一致,那么我们可以认为这两个url就是同源的
举例
https://qq.com、https://www.baidu.com不同源
http://baidu.com、https/www.baidu.com 不同源
完全一致才算同源
同源策略定义
浏览器规定
- 如果JS运行在源A里,那么就只能获取源A的数据
- 不能获取源B的数据,即不允许跨域
举例(省略http协议)
- 假设xiaobangsky.com/index.html引用了cdn.com/1.js
- 【1.js运行在源xiaobangsky.com里】
- 跟cdn.com没关系,虽然1.js从它那下载
- 因此1.js只能获取xianbangsky.com的数据
- 不能获取1.xiaobangsky.com或者qq.com的数据
这是浏览器的功能
- 浏览器故意这么设计的
- 目的是为了保护用户的隐私
如果没有同源策略
以qq空间为例:
- 源为 https://user.qzone.qq.com
- 假设当前用户已经登陆(用Cookie)
- 假设Ajax请求/friend.json可获取用户好友列表
- 到目前为止都很正常
黑客来了:
- 假设你的女神分享 https://qzone-qq.com给你
- 实际上是一个钓鱼网站
- 你点开这个网页,这个网页也请求你的好友列表
- https://user.qzone.qq.com/friend.json
- 请问你的好友列表是不是就被黑客偷走啦
- 好像是。。。。。
问题的根源
无法区分发送者:
- QQ空间页面里的js和黑客网页里的js
- 发送的请求几乎没有区别(referer有区别):什么是referer?当一个用户点击当前页面中的一个链接,然后跳转到目标页面时,目标页面会收到一个信息,即用户是从哪个源链接跳转过来的
- 如果后台开发者没有检查referer,那么就没区别
- 因此,没有同源策略,任何页面都能偷qq空间的数据、
- 甚至支付宝余额
那么检查referer不就好了?
- 安全原则:安全链条的强度取决于最弱一环
- 万一这个网站的后端开发工程师是个小白呢?
- 所以浏览器要主动预防这种偷数据的行为
- 总之,浏览器为了用户的隐私,设置了严格的同源策略
CORS
- CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)
- 它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制
举例
- 浏览器默认不同源之间不能相互访问数据
- 但是qq.com和xiaobangsky.com其实是同一家公司的网站
- 这家公司想要两个网站能够相互访问,浏览器为啥要阻止
解决办法
- 浏览器说,如果要共享数据,需要提前说明
- 怎么声明 :浏览器说,qq.com在响应头里面写xiaobangsky.com可以访问
- 具体语法 :‘Access-Control-Allow-Origin’,‘http://xiaobangsky.com:9999’
- 浏览器说:都在文档里面,去看MDN文档
- 缺点:不支持IE6\7\8\9
JSON
- JSONP和JSON半毛钱关系都没有
- 由于前端水平低下,错误的将其称为JSONP
- JSONP实现跨域请求的原理简单的说,就是动态创建
优点
- 兼容IE
- 支持跨域
缺点
- 由于它是script标签,它不知道响应的状态,不知道响应的状态码,只知道成功或者失败。
- 只能发get请求,不能发post请求
案例
xiaobangsky.com访问qq.com
qq.com用script标签引用/friends.js
/friends.js执行,执行什么呢?
xiaobangsky.com事先定义好的window.xxx函数
/friends.js执行window.xxx({freinds:[...]})
然后xiaobangsky.com就通过window.xxx获取到数据了
window.xxx就是一个回调呀
具体代码
跨域实现demo