今天早上在外面跑了一天,晚上可能还要去撸串,想了下,写一篇同源策略的吧。
前言
同源策略,是浏览器安全上的一个定义,概念很简单,但在实际应用中,还是比较经常使用的,特别是公司产品线丰富后,需要进阶到微前端等概念时,需要对其进行技术支持处理的一个方向。
概念
前言里也说了,同源策略是浏览器安全的基础。这边具体说下什么是同源策略:
在你对网页做一定的操作时,比如读取Cookie、LocalStrorage、IndexDB、DOM操作、发起Ajax,那么操作与被操作页面则必须满足下列三个相同
-
协议相同
-
域名相同
-
端口相同
所以统一称为同源策略
例:www.toutiao.com/page.html这个…
-
为什么
为什么要同源呢?因为这样安排,否则黑客可以很简单的通过CSRF来进行攻击。假如没有同源策略,我会这样做:
- 首先,我有一个暗恋的女孩
- 然后,我写了一个恶意页面www.heheda.com,里面的脚本可以获取Cookie信息,与可以伪造Ajax请求代理,向taobao发送请求
- 然后我就知道这个女孩的购物车,我发现他加了很多男士用品,看来他有男朋友了
- 我很生气,然后清空了她的购物车
当然,上面的场景很扯淡,首先,我没有暗恋的女孩,小孩才暗恋,成年人直接深入浅出,其次,不可能没有同源策略限制。
导致的问题
- 跨域问题
我们回归正题,同源策略在早期是没什么问题,可是随着微服务的发展,问题的比较明显了,因为很多微服务域名是都不同的,而一个前端通常情况下,需要对接N个微服务的。这就是跨域问题。
- 页面通信问题
有时,我们是希望在多个页面间进行通信,但由于同源策略导致的DOM限制操作,我们是不能直接通过iframe操作其它非同源页面的DOM的
- 通用存储问题
你想建立一个统一的前端数据库,用在多个微服务前端页面共用数据,不好意思,这也不行
跨域问题解决方案
- CORS方案(跨域资源共享)
CORS即Cross-origin resource sharing,是一个W3C标准,定义了跨域资源时浏览器与服务器沟通方案。这个方案是由服务器处理的,前端基本不需要处理。对前端开发者来说,非常透明,操作不需要做什么。
目前CORS是主流方案,但它有个缺点,就是浏览器需要IE10以上。
使用CORS,你会发现你在发起非简单请求时,浏览器会发起两次请求,其实浏览器在发送真正的请求之前,会先发送一个 Preflight 请求给服务器,这种请求使用 OPTIONS 方法,发送下列头部:
- Origin:与简单的请求相同。
- Access-Control-Request-Method: 请求自身使用的方法。
- Access-Control-Request-Headers: (可选)自定义的头部信息,多个头部以逗号分隔。
发送这个请求后,服务器可以决定是否允许这种类型的请求。服务器通过在响应中发送如下头部与浏览器进行沟通:
- Access-Control-Allow-Origin:与简单的请求相同。
- Access-Control-Allow-Methods: 允许的方法,多个方法以逗号分隔。
- Access-Control-Allow-Headers: 允许的头部,多个方法以逗号分隔。
- Access-Control-Max-Age: 应该将这个 Preflight 请求缓存多长时间(以秒表示)。
一旦服务器通过 Preflight 请求允许该请求之后,以后每次浏览器正常的 CORS 请求,就都跟简单请求一样了。
- JSONP方案
这个就是纯前端方案了,他的原理就是利用了浏览器对Script脚本可以加载非同源脚本的功能,用这个功能进行请求处理,当然,这只能进行请求数据,提交数据就无能为力了。
非常不建议使用这个方案。
- WebSocket
这货直接无视同源策略,因为WebSocket请求时,会带一个Origin信息,这个信息就是请求者信息,服务端是知道谁请求的,所以说,大家都知根知底,就没必要做些多余的事了。
- 反向代理方案
这个也是需要配置服务器的,目的也是直接通过代理进行域名变更。不同服务器配置不同,有兴趣可以搜索下配置信息
- BFF方案
BFF就是Back-end For Front-end,中文是服务前端的后端,就是用Node.js开发一个服务于前端的后端,这样这个后端就和前端是同源的,而和微服务的请求是由Node.js来发起,因为不是浏览器,所以就没有同源的限制了。
BFF可以说一本书,这边就不展开了
页面通信问题解决方案
- PostMessage
这个是H5的跨域页面通信方案,目前基本都是用这货。
通用存储问题
其实现在都是组件化了,微前端化,有时候,需要通用存储问题,这时,最好的方案当然就是统一域名化了。
实践
使用PostMessage写一个页面消息传递,再思考下,有没有其它方案
了解下CORS实现方案,用Node.js写一个服务端,自己实现下跨域请求