跨域问题
同源策略
什么是同源?
如果两个页面的协议、域名和端口都相同,则两个页面具有相同的源。
什么是同源策略
同源策略是浏览器提供的一个安全功能。
MDN 官方给定的概念:同源策略限制了一个从同一个源加载的文档或脚本如何与来自另一个新的源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
跨域
什么是跨域?
服务器为了保护数据安全,只允许同源请求获取响应体数据,如果是跨域请求,不能正确的获取响应体数据,会有跨域访问报错。
出现跨域的根本原因:浏览器的同源策略不允许非同源的 URL 之间进行资源的交互。
浏览器对跨域请求的拦截
如何解决跨域问题?
1 cors
CORS,全称跨域资源共享, 由一系列 HTTP 响应头组成,这些 HTTP 响应头决定浏览器是否阻止前端 JS 代码跨域获取资源。
浏览器的同源安全策略默认会阻止网页 “跨域” 获取资源。但如果接口服务器配置了 CORS 相关的 HTTP 响应头,就可以解除浏览器端的跨域访问限制。
注意:
- CORS 主要在服务器端进行配置。客户端浏览器无须做任何额外的配置
- CORS 在浏览器中有兼容性。目前基本都满足,IE浏览器不能低于IE10+
在Express框架中:
使用步骤分为如下3步:
运行npm install cors
安装中间件
使用const cors=require('cors)
导入中间件
在路由之前调用app.use(cors())
配置中间件
// 在路由之前,配置cors这个中间件,从而解决接口跨域的问题
const cors = require('cors')
app.use(cors())
// 挂载路由
app.use("/api", router)
原生Nodejs:
app.use((res, req, next)=> {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, HEAD,DELETE,OPTIONS');
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header('Access-Control-Allow-Headers', ['mytoken','Content-Type']);
})
CORS 请求的分类
客户端在请求 CORS 接口时,根据请求方式和请求头的不同,可以将 CORS 的请求分类分为两大类,分别是:
- 简单请求
- 预检请求
简单请求
同时满足以下三大条件的请求,就属于简单请求:
- 请求方式:GET、POST、HEAD 三者之一
- HTTP 头部信息不超过以下几种字段:无自定义头部字段、Accept、Accept-Language、Content-Language、DPR、DownLink、Save-Data、Viewport-Width、Width、
- Content-Type: application/x-www-form-urlencoded、multipart/form - data、text/plain
预检请求
只要符合以下任何一个条件的请求,都需要进行预检请求:
- 请求方式为 GET、POST、HEAD 之外的请求 Method 类型
- 请求头中包含自定义头部字段
- 向服务器发送了 application/json 格式的数据
在浏览器与服务器正式通信之前,浏览器会先发送 OPTION 请求进行预检,以获取服务器是否允许该实际请求,所以这一次的 OPTION 请求称为 “预检请求”。服务器成功响应预检请求后,才会发送真正的请求,并且携带真实数据。
简单请求和预检请求的区别
简单请求的特点:客户端与服务器之间只会发生一次请求。
预检请求的特点:客户端与服务器之间会发生两次请求,OPTION预检请求成功之后,才会发起真正的请求。
2 服务器代理
使用vite创建的项目,修改vite.config.js配置文件:
server: {
host: "127.0.0.1", // ip
port: 8089, // 端口号
open: false, // 是否自动在浏览器打开
https: false, // 是否开启 https
// 跨域代理配置
proxy: {
'/api': {
// 匹配所有以api开头的路径
target: 'http://localhost:8082/api/', // 目标地址
changeOrigin: true, // 是否允许跨域
rewrite: path => path.replace(/^\/api/, '')
}
}
}
3 JSONP
原理:
1、服务器对于src的跨域请求不会阻止。
2、script标签src导入的外部文件,内容/输出 都会按照JavaScript语法程序执行。
限制:仅支持 GET 方法。
注意:
如果项目中已经配置了 CORS 跨域资源共享,为了防止冲突,必须在配置 CORS 中间件之前声明 JSONP 的接口。否则 JSONP 接口会被处理成开启了 CORS 的接口。