跨域
什么是跨域
在解释跨域之前,需先了解同源策略
同源策略
指在 Web浏览器 中允许某个网页 脚本 访问另一个网页数据。前提是两个网页具有相同的 URI、域名/主机、端口号
关于 URI、域名和端口,请看以下示例
|
|
一般判定同源只需要判定三个部分——scheme,host,port
因此通常情况下 URI 指的是——协议(scheme)
关于浏览器请求的协议部分,内容比较多,我将另起一个章节
为什么会有同源策略
由于 Web应用程序 广泛依赖于 HTTP Cookie 来维持会话,出于安全性考虑,必须将不相关的网站严格分离,以防止数据丢失泄露
因此,有了同源策略的概念之后,什么是跨域也呼之欲出了。是的,所有不满足同源策略的访问,都是跨域
如何实现跨域访问
jsonp
-
原理:同源策略只限制在 JS 脚本,HTML 的标签是不受约束的
-
应用场景:CDN 在线资源请求
-
实现方式:
1 2 3 4 5 6
<!--- 如果是图片、视频等 ---!> <img src="http:exampe.test.com:80/back.png" /> <video src="http:exampe.test.com:80/demo.mp4" /> <!--- 如果是JSON、JS等 ---!> <script type="text/java" src="http:exampe.test.com:80/demo.js" />
1 2 3 4 5 6 7 8 9 10 11
/* 通过 JS 文件动态创建 */ // cross.js function addScript(src) { const script = document.createElement("script"); script.setAttribute("type", "text/javascript"); script.src = src; document.body.appendChild(script); } window.onload = function () { addScript("http:exampe.test.com:80/demo.js"); };
CORS
-
原理:HTTP 请求头可以设置跨域
-
应用场景:访问白名单,公共访问接口
-
实现方式:
setHeader
方法根据不同的请求库自行切换1 2 3 4 5 6 7 8 9 10 11 12
// 设置哪个源可以访问我 setHeader('Access-Control-Allow-Origin', '[*|url]') // 允许携带哪个头访问我 setHeader('Access-Control-Allow-Headers', 'name') // 允许哪个方法访问我 setHeader('Access-Control-Allow-Methods', 'PUT') // 允许携带cookie setHeader('Access-Control-Allow-Credentials', true) // 预检的存活时间 setHeader('Access-Control-Max-Age', 6) // 允许返回的头 setHeader('Access-Control-Expose-Headers', 'name')
window.postMessage
-
应用场景:多窗口数据传递,iframe 数据传递
-
实现方式:
1 2 3 4 5 6 7 8 9 10 11
/* example.test.com:3001/index.js */ window.postMessage("hello", "example.test.com:3002"); window.onmessage = function (e) { console.log(e.data); // nice to meet you }; /* example.test.com:3002/index.js */ window.onmessage = function (e) { console.log(e.data); // hello e.source.postMessage("nice to meet you", e.origin); };
WebSocket
-
原理:HTTP 请求经过桥接升级为 WS 长连接,此时客户端与服务器可以互相通信
-
应用场景:聊天、直播、联机游戏等所有需要实时交互的场景
-
实现方式:
1 2 3 4 5 6 7 8 9 10 11 12
/* client */ const socket = new WebSocket("ws://example.test.com:3002"); window.postMessage("hello", "example.test.com:3002"); socket.open = function () { socket.send("hello"); }; socket.onmessage = function (e) { console.log(e.data); // nice to meet you }; /* service */ // 监听 WS 请求
Node中间代理
- 原理:同源策略限制在浏览器端,服务器向服务器请求不受同源策略限制
- 应用场景:一般用于开发环境的本地代理,就是启动了一个本地服务器,向服务器请求资源
Nginx 反向代理
- 原理:同 node 中间代理,实现方式一样,代理目标相反
- 应用场景:一般用于前后端分离项目,生产环境的服务器代理
- 与中间代理的差异:中间代理在客户端配置代理,将客户端代理到服务器;反向代理在服务器配置,将监听到的端口转发到目标服务
- 点此了解更多 Nginx 内容