要解决浏览器跨域问题 就要先了解什么是浏览器的同源策略
- 同源策略是一个重要的安全策略,它用于限制一个origin(源)的文档或者它加载的脚本如何能与另一个origin(源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。
当我们从静态资源服务器 请求到了html/css/js 在js中会包含着网络请求 这个时候就会经过浏览器的同源策略 如果 协议 host 端口不一致 就会出发CORS 产生跨域
浏览器发现静态资源和API接口(XHR、Fetch) 请求不是来自同一个地方时(同源策略),就产生了跨域。
同源策略是在保护服务器 防止未知脚本注册到服务器上 然后获取到数据触发利益的损害
- 这个方案也被称为“协议/主机/端口元组”,或者直接是“元组”。
跨域的常用四种解决办法
- 方案一:静态资源和API服务器部署在同一个服务器中;
- 方案二:CORS, 即是指跨域资源共享;
- 方案三:node代理服务器(webpack中就是它);
- 方案四:Nginx反向代理;
1. 静态资源和api部署在一起
使用koa中的static(静态资源中间件) 部署到一起
直接访问8080端口 也就是koa开启的服务器。 这样就把静态资源和api在同一个服务器中
这种方式会把单一的服务器内部资源占满 越来越多
2.CORS, 即是指跨域资源共享;
它是一种基于http header的机制; 该机制通过允许服务器标示除了它自己以外的其它源(域、协议和端口),使得浏览器允许这些 origin 访问加载自己的资源。也就是说给服务器标识除了自己以外 还有谁可以来进行访问
浏览器将 CORS 请求分成两类:简单请求和非简单请求 Vue3+TypeScript
◼请求方法是以下是三种方法之一: HEAD GET POST
◼ HTTP 的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值 application/x-www-form-urlencoded、multipart/form-data、text/plain
满足上面的情况的都是简单请求 否则都是非简单请求
app.use(async (ctx, next) => {
// 1.允许简单请求开启CORS *代表着所有源。 也可以单独设置一个
ctx.set("Access-Control-Allow-Origin", "*")
// 2.非简单请求开启下面的设置
ctx.set("Access-Control-Allow-Headers", "Accept, AcceptEncoding, Connection, Host, Origin")
ctx.set("Access-Control-Allow-Credentials", true) // cookie
ctx.set("Access-Control-Allow-Methods", "PUT, POST, GET, DELETE, PATCH, OPTIONS")
// 3.发起的是一个options请求
if (ctx.method === 'OPTIONS') {
ctx.status = 204
} else {
await next()
}
})
3.node代理服务器(webpack中就是它);
如果直接访问api服务器就会出发浏览器的同源策略 所以可以开启一个node服务器(本质也就是node程序) 然后通过node服务器 来访问api服务器 因为是通过node服务器来访问 他不属于浏览器访问 所以不存在有跨域问题
其实webpack 配置中proxy也是使用的http-proxy-middleware软件包开启了一个node代理服务器
// webpack => webpack-dev-server
const express = require('express')
const { createProxyMiddleware } = require('http-proxy-middleware')
const app = express()
// 把代理服务器 和静态资源服务器部署到一起
app.use(express.static('./client'))
app.use('/api', createProxyMiddleware({
target: "http://localhost:8000",
pathRewrite: {
'^/api': ''
}
}))
app.listen(9000, () => {
console.log('express proxy服务器开启成功')
})
4.使用Nginx 开启反向代理
Nginx 他可以在内部来进行源的验证 来阻拦其它未知源的访问。 避免暴漏api服务器的ip地址 提高安全性