同源策略及其规避方法
同源
-
所谓"同源"指的是"三个相同"。
- 协议相同
- 域名相同
- 端口相同
同源策略
-
背景:1995年,同源政策由 Netscape 公司引入浏览器。目前,所有浏览器都实行这个政策。
-
概念
-
最初的概念
A网页设置的 Cookie,B网页不能打开,除非这两个网页"同源"
-
后续发展的概念:https://cifer76.github.io/posts/same-origin-policy/
-
允许在浏览器中从 originB 内部请求 originA 的远程资源,包括跨域嵌入和跨域写入远程资源
<a href=...
指示浏览器请求另一个资源的 HTML标记<form action=... method="POST">
使浏览器将表单发布到另一个网站的 HTML标记<link rel="stylesheet" href="…">
从另一个站点加载 CSS 样式并将其嵌入到我们自己的网页的标签<img>
从别处加载图像并将其嵌入到我们自己的网页的标签<script>
从其他地方加载 javascript 代码片段并嵌入到我们自己的网页中的标签XMLHttpRequest
AJAX 请求- Web 字体(用于 CSS 中 @font-face 中的跨域字体使用)
- 浏览器允许1-5个场景,而屏蔽6和7,还有其他场景,浏览器也屏蔽,你可以检查这个链接,查看所有被浏览器屏蔽的场景:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS#what_requests_use_cors(可以暂时放下)
-
不允许在浏览器中从 originB 内部请求 originA 的远程资源,即不允许跨域读取以下三种已加载资源和行为
(1) Cookie、LocalStorage 和 IndexDB 无法读取。
(2) 页面的DOM 无法获得。
(3) js方法无法调用
(4) AJAX 请求不能发送。
-
-
突破同源策略
具体实现请看:https://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html
一级域名相同下的cookie和iframe/window.open打开的弹出层窗口的(2)(3)
类资源跨域
-
document.domain
Cookie 是服务器写入浏览器的一小段信息,只有同源的网页才能共享。但是,两个网页一级域名相同,只是二级域名不同,浏览器允许通过设置
document.domain
共享 Cookie。cookie的两种方式:
- 客户端设置:A网页通过
document.domain
设置一个cookie,B网页就能通过document.domain
获取到这个cookie - 服务端设置:服务端设置cookie时,通过
domain
属性指定Cookie的所属域名为一级域名
子窗口的跨域方式:https://segmentfault.com/a/1190000005863659
- a.html里与b.html里都加入:
document.domain = "xxx.com";
- 客户端设置:A网页通过
完全不同源的cookie和iframe/window.open打开的弹出层窗口的(2)
类资源跨域
-
片段识别符(fragment identifier)
- 主要逻辑是片段标识符
#fragment
绑定所需的跨域数据,通过监听hashchange
事件获取跨域数据
- 主要逻辑是片段标识符
-
window.name
- 主要逻辑是子窗口通过
window.name
设置跨域数据,回到父窗口通过document.getElementById('{子窗口id}').contentWindow.name;
获取跨域数据
- 主要逻辑是子窗口通过
(4)
资源跨域方法
- JSONP
- 主要逻辑是网页动态插入
<script>
元素,由它向跨源网址发出请求 - Spring中的应用:https://www.jb51.net/article/110847.htm
- 主要逻辑是网页动态插入
- WebSocket
- WebSocket请求的头信息的
Origin
字段设置
- WebSocket请求的头信息的
- CORS
- 它是W3C标准,是跨源AJAX请求的根本解决方法。相比JSONP只能发
GET
请求,CORS允许任何类型的请求。 - CORS是什么:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS#what_requests_use_cors
- 解决:https://www.ruanyifeng.com/blog/2016/04/cors.html
- 它是W3C标准,是跨源AJAX请求的根本解决方法。相比JSONP只能发
所有资源跨域
-
概念:https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage
HTML5为了解决这个问题,引入了一个全新的API:跨文档通信 API(Cross-document messaging)。
这个API为
window
对象新增了一个window.postMessage
方法,允许跨窗口通信,不论这两个窗口是否同源。 -
实现
(1)
资源跨域:见3.4 -
实现
(2)(3)
资源跨域:见3.3跨域调用不同js方法来获取,DOM在js方法中获取回传即可 -
实现
(4)
资源跨域:见3.3跨域调用不同js方法,通过数据跨传,在需要发送AJAX请求的js方法中发送。