同源策略(Same-Origin Policy),是Javascript里很重要的一种安全限制。这一策略限制了Javascript代码只能访问与包含它的文档在同一域名、协议、端口号下的页面内容。跨域是一种网络通信上的概念,从前段到前端、前段到后端都会存在跨域的情况。
跨域的类型分为以下几种:
图片说明
在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。比如上面表格第五行的http://www.a.com/a.jshttp://70.32.92.74/b.js 。虽然域名和域名的ip对应,不过还是被认为是跨域。

跨域的常见场景&解决办法:
1. ajax请求跨域(前端与后端通信)
1.1 CORS策略
CORS(Cross-origin resource sharing)是一套前后端用于允许跨域通信的约定机制
图片说明

当跨域发送cookie时需要额外设置withCredentials相关头。
cookie是前后端通信中常用于校验凭证等数据传输的数据载体,比如在a.qq.com的网站上,请求了一个c.qq.com/xxx.php 的接口,但是此接口需要从c.qq.com的域名下拿cookie中的登录态作为身份校验,这时就会发现cookie取不到。

1.2 jsonp
在页面上有三种资源是可以与页面本身不同源的。它们是:js脚本,css样式文件,图片,像淘宝等大型网站,肯定会将这些静态资源放入cdn中,然后在页面上连接。而jsonp的本质就是利用了script标签的src属性是没有跨域的限制的,从而达到跨域访问的目的。因此它的最基本原理就是:动态添加一个script标签来实现。
使用jsonp方式跨域的优点很明显,就是兼容性强;缺点就是jsonp本质上是script请求,只能支持GET请求,对于大数据量和传输文件等都不支持,而且也无法拿到相关的返回头,状态码等数据。

2. https资源跨域(协议不一致,http与https)
对于前端http页面,请求后端https接口,不会报错。
但是对于前端https页面,请求后端http接口,就一定会被浏览器阻挡,因为https设计之初就要求,页面所有内容必须以加密方式传输,那么对于页面上的请求,也同样有此要求。理论上https页面的请求需要全部用https,除了规范协议这里没有比较好的解决方法。

3. 前端跨域通信(前端与前端)
图片说明
两个不符合同源策略的页面之间进行的函数调用,上下文空间访问等行为均属于前端跨域通信的范畴。

3.1 postmesssage(H5适用)
postMessage是H5体系下自带的一种前端页面间通信方案,可以实现父页面和子页面之间的通信(iframe),以及浏览器中两个tab页之间的通信(前提是两个页面有依赖关系,比如B页由A页打开)。

3.2 降域通信(documetn.domain设置)
降域通信是一种比较老的前端跨域通信解决方案,它适用于所有浏览器。但是必须要求两个互相通信的页面其域名至少公用同一个二级域名:
比如:a.qq.com与b.qq.com都共用qq.com这个二级域名。
但是www.qq.comwww.baidu.com 就不具备这种关系。
这种跨域方案利用了前端降域的特性,即对于任何一个二级或二级以上域名,都可以利用document.domain来设置其值为该页面domain的公共部分。
比如:a.b.c.d.com 这个页面,可以利用document.domain设置成:
b.c.d.com、c.d.com、d.com三种值。
而两个页面进行前端通信的时候,同源策略将会判断document.domain的值,而不是页面本身的域名。如果documetn.domain值一致则满足同源策略。
如下图所示,两个页面均降域到相同的域名后,就满足同源策略了,也就不再受浏览器跨域策略的影响,可以正常通信。
图片说明

参考文献:
web跨域解决方案:
https://cloud.tencent.com/developer/article/1052030
浏览器的同源策略:
https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy