本文已参与掘金创作者训练营第三期「话题写作」赛道,详情查看:掘力计划|创作者训练营第三期正在进行,「写」出个人影响力
什么是 XMLHttpRequest?
XMLHttpRequest
(XHR)对象用于与服务器交互。通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容。
XMLHttpRequest
在 AJAX 编程中被大量使用。
什么是跨域?
跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对 JavaScript 施加的安全限制。
什么是同源策略?
同源策略是一个重要的安全策略,它用于限制一个 origin 的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。
下表给出了与 URL https://juejin.cn
的源进行对比的示例:
URL | 结果 | 原因 |
---|---|---|
https://juejin.cn/user_api/v1/user/profile_id | 同源 | 只有路径不同 |
http://juejin.cn/interact_api | 跨域 | 协议不同 |
https://juejin.cn:8888/list_api | 跨域 | 端口不同 ( http:// 默认端口是80) |
https://mcs.snssdk.com/v1/list | 跨域 | 主机不同 |
为什么不让跨域?
同源策略的目的是为了保证网络安全,防止数据被恶意窃取。
以下三种行为会受到限制:
- Cookie、LocalStorage 和 IndexDB 无法读取
- DOM 无法获得
- AJAX 请求不能发送
如何解决跨域问题?
CORS
Cross-origin resource sharing (跨域资源共享) 简称 CORS。
一般是从请求中读取 Origin 标头并包含一个响应标头,说明请求源是被允许的。例如,考虑一个接收以下请求的应用程序:
GET /sensitive-victim-data HTTP/1.1
Host: vulnerable-website.com
Origin: https://malicious-website.com
Cookie: sessionid=...
然后它响应:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://malicious-website.com
Access-Control-Allow-Credentials: true
...
这些标头声明允许来自请求域 ( malicious-website.com
) 的访问,并且跨域请求可以包含 cookie ( Access-Control-Allow-Credentials: true
),因此将在会话中进行处理。
Nginx 代理
nginx 配置解决 iconfont 跨域
浏览器跨域访问 js、css、img 等常规静态资源被同源策略许可,但 iconfont 字体文件 (eot|otf|ttf|woff|svg) 例外,此时可在 nginx 的静态资源服务器中加入以下配置。
location / {
add_header Access-Control-Allow-Origin *;
}
nginx 反向代理接口跨域
可以跨域的原理:同源策略是浏览器的安全策略,不是 HTTP 协议的一部分。服务器端调用 HTTP 接口只是使用 HTTP 协议,不会执行 JS 脚本,不需要同源策略,也就不存在跨越问题。
实现思路:通过 nginx 配置一个代理服务器(域名与 domain1 相同,端口不同)做跳板机,反向代理访问 domain2 接口,并且可以顺便修改 cookie 中 domain 信息,方便当前域 cookie 写入,实现跨域登录。
nginx 具体配置:
#proxy服务器
server {
listen 81;
server_name www.domain1.com;
location / {
proxy_pass http://www.domain2.com:8080; #反向代理
proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名
index index.html index.htm;
# 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用
add_header Access-Control-Allow-Origin http://www.domain1.com; #当前端只跨域不带cookie时,可为*
add_header Access-Control-Allow-Credentials true;
}
}
Nodejs 代理
利用服务端之间请求不会跨域的特性
- webpack 配置 proxy
- Vue-cli 中配置 proxy
WebSocket
WebSocket protocol 是 HTML5 一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯,是 server push 技术的一种很好的实现。
// 初始化一个 WebSocket 对象
var ws = new WebSocket("ws://localhost:9999/echo");
// 建立 web socket 连接成功触发事件
ws.onopen = function () {
// 使用 send() 方法发送数据
ws.send("发送数据");
alert("数据发送中...");
};
// 接收服务端数据时触发事件
ws.onmessage = function (evt) {
var received_msg = evt.data;
alert("数据已接收...");
};
// 断开 web socket 连接成功触发事件
ws.onclose = function () {
alert("连接已关闭...");
};
总结
- 域名、协议和端口不同时会导致跨域现象
- 常见解决跨域问题的方法要牢记在心
- 本文介绍的内容都比较粗略,欢迎在评论区补充细节