七种常见的跨域解决方案
前言
作为一名开发人员,相信无论是在项目中还是面试中,都会经常听到跨域这个词。大家或多或少对于跨域都有一定的了解。那么你知道几种跨域方式呢?欢迎在评论区留言。
什么是跨域?
浏览器出于安全考虑,只允许访问请求在相同域名相同端口相同协议下的脚本和接口。
协议、域名、端口有一个不满足的话 就会造成跨域。
浏览器实现了一种约定俗成的安全模式 -> 同源策略
| URL | 说明 | 是否允许通信 |
|---|---|---|
| https://www.baidu.com/banner.js https://www.baidu.com/search.js |
相同域名下 | 允许通信 |
| https://www.baidu.com:8080/detail.js https://www.baidu.com/8000/apollo.js |
相同域名 不同端口 | 不允许通信 |
| https://www.baidu.com/test/date-range.js https://www.baidu.com/utils/validate.js |
相同域名 下不同文件夹中 | 允许通信 |
| http://www.google.com/banner.js https://www.google.com/search..js |
相同域名 不同协议 | 不允许通信 |
| https://bytedance.wenjuan.com/userInfo/question.html https://live.wenjian.com/userInfo/question.html |
主域相同 子域不同 | 不允许通信 |
| http://12.35.46.87/login.js http://blog.mintureChan/login.js |
域名与域名对应的ip相同 | 不允许跨域 |
| http://blog.mintureChan/login.js http://mintureChan/login.js |
域名相同 二级域名不同 | 不允许跨域 |
| https://www.baidu.com/banner.js https://www.google.com/banner.js |
不同域名 | 不允许跨域 |
如上是各种不同方式的通信请求对比。
同源策略
在浏览器中分别打开tab页面百度和谷歌
当浏览器的百度tab页执行一个脚本时 会检查这个脚本属于哪个页面。
即检查是否同源,只有和百度同源的脚本才会被执行。
如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。
同源策略是浏览器的行为,是为了保护本地数据不被JavaScript代码获取回来的数据污染,因此拦截的是客户端发送请求的响应,即请求发送了,服务器响应了,但是无法被浏览器接收。
跨域解决方式
jsonp
jsonp是json的一种使用模式。HTML中<script>标签元素实现了这种使用模式。使用script标签可以获取到任意动态的JavaScript。
注意:script标签通过JavaScript直译器执行而不是用 JSON 解析器解析。
//使用jsonp获取fly.js |
使用场景:访问部署在不同域名下的包或访问第三方的sdk等。
jsonp的缺点: jsonp请求只支持get请求。 jsonp传输的文件可能会导致xss的攻击。
postMessage解决跨域
postMessage是web的一个Api window.postMessage()提供了一种受控机制来规避同源的这种安全模式。只要合理使用也可以很安全。
postMessage允许你从一个iframe向另一个iframe发送MessageEvent。所接收的page用window. addEventListener('message',( receiveMessage)=>{ //do some thing })来获取到发送页面的消息。
使用场景:在项目中对其他非同源部署的项目上进行通信传输。如: 项目中嵌套iframe地图发送骑手配送消息。
postMessage缺点:每次发送消息都需要进行监听 发送者和接收者都需要进行配置。并且在多次分发下显得代码重复臃肿。
CORS(跨域资源共享)
CORS (Cross-Origin Resource Sharing,跨域资源共享)是一个系统,它由一系列传输的HTTP头组成,这些HTTP头决定浏览器是否阻止前端JavaScript代码获取跨域请求的响应。
同源策略默认阻止“跨域”获取资源。但是 CORS 给了web服务器权限,CORS允许跨域请求访问到不同源下的其他资源
当使用 XMLHttpRequest 发送请求时,浏览器会判断请求是否符合同源策略。如果不符合同源策略 浏览器会给该请求添加一个请求头-> Origin
跨域资源共享配置可以由后端进行配置也可以由前端进行配置
//ajax 实现CORS跨域 |
//我们可以在java的请求拦截器中对部分需要跨域的接口进行处理 |
值得注意的是 如果前端给请求头携带Cookie.后端一定需要配置Access-Control-Allow-Credentials
使用场景: 适用于不同服务之间的跨域请求。是目前主流的跨域解决方案之一
websocket实现跨域
websocket和HTTP都是基于TCP协议的 因此使用websocket进行通信不需要考虑跨域的问题
但使用websocket进行通信需要保证websocket的唯一状态
//客户端
npm i socket.io --save
//假设页面存在id为myH3的dom
var domRender = document.getElementById('myH3')
let io = require("socket.io")
io.connect('http://localhost:8081');
io.on('data',(data)=>{
myH3.innerHTML = data
})
//用node作为服务端向客户端发送信息
var httpServer = require('http').createServer();
var io = require("socket.io")(httpServer);
httpServer.listen(8080);
io.on("connection",function(client){
//客户端发送数据
client.emit("data","hello WebSocket from 8081");
});
这种通信方式也可以当作是一种跨域的解决方案
使用场景:适用于实时消息接收与发送。
nginx反向代理实现跨域
nginx作为一款轻量性的高性能web服务器 受到了无数开发人员的喜爱。它体积小。并发能力强,非常适合作为一个代理服务器进行分发。 使用nginx作为跨域解决方案也是目前开发者使用最多的一种方式
在本地起一个端口号为8070的node服务
假设在本地9998端口运行了如上图这个html文件 打开控制台会报出一个跨域的错误。我们使用nginx反向代理来解决这个问题。
下载nginxnginx的配置一般由后端开发人员进行。一般使用的都是linux版本 为了方便 这里我就使用window版本的nginx进行配置
如上图 解压之后的nginx目录下会有这些文件夹。进入到 config文件夹中。找到一个名为nginx.conf的文件 这个文件就是nginx的基础配置文件。打开后进行修改:
监听localhost:9998端口 配置一个请求的代理。。将localhost:9998端口下所有经过/api/的请求路径全部代理到localhost:8070上 也就是说访问http://localhost:9998/api/getUserInfo的请求实际上变成了访问 http://localhost:8070/api/getUserInfo。该方式被称为反向代理。
再次启动9998端口访问html文件 控制台打印出了响应的信息。
node中间件代理跨域
使用node中间件进行代理跨域的原理和nginx代理跨域的原理基本一样 都是通过一个代理服务器的请求将数据进行转发实现同源操作。
var xhr = new XMLHttpRequest(); |
中间件服务器代码:
var express = require('express'); |
webpack-dev-server
如果你使用过vue-cli + webpack搭建项目 那么webpack-dev-server 你一定不陌生。脚手架搭建项目 在本地启动的服务使用的就是webpack-dev-server 你可以在 package.json中的快捷执行命令行看到 npm run dev 后面执行的代码
在开发环境下 我们通常也会访问其他服务 比如文件服务,音视频服务。也会造成跨域的问题。在vue-cli项目中 我们可以修改vue.config.js文件中devServer这一项配置来解决开发环境中的跨域问题。
//vue.config.js |
在本地端口8088中访问的所有包含/api的路径地址都会被代理到http://minture-chan-glitch.com 这种代理依靠的就是webpack-dev-server
最后
文本一共总结了七种跨域解决方案 希望能对你有所帮助。如果觉得文章有不妥之处 还请大家批评支持。
感谢您观看此篇文章 希望能给个👍评论收藏三连!你的点赞就是我写作的动力。




