很多刚学前后端的人:
第一次看到:
txt
CORS error
跨域
Access-Control-Allow-Origin
都会特别懵。
甚至:
会感觉:
txt
明明后端接口没问题
为什么前端请求失败?
其实:
问题不在后端逻辑。
而在:
txt
浏览器安全机制
一、什么是 CORS
CORS:
全称:
txt
Cross-Origin Resource Sharing
中文:
txt
跨域资源共享
一句话:
txt
浏览器允许不同网站之间互相请求数据的规则
二、为什么会有跨域
浏览器:
默认:
txt
不允许不同源之间互相访问
这是:
txt
浏览器的同源策略
三、什么是"同源"
必须:
这三个都一样:
txt
协议
域名
端口
才叫:
txt
同源
四、举例(重点)
这个算同源
txt
http://localhost:3000
http://localhost:3000
这个不算
端口不同:
txt
http://localhost:3000
http://localhost:8080
这个也不算
协议不同:
txt
http://example.com
https://example.com
这个也不算
域名不同:
txt
http://a.com
http://b.com
五、为什么浏览器要限制
因为:
如果不限制:
恶意网站:
可能:
txt
偷偷请求你的银行接口
非常危险。
六、最经典跨域场景
前端:
运行:
txt
http://localhost:5173
Vue/React 开发服务器。
后端
Gin:
运行:
txt
http://localhost:8080
前端请求后端
js
fetch("http://localhost:8080/user")
七、结果
浏览器:
直接报错:
txt
CORS error
八、为什么 Postman 没问题
很多新人:
这里会懵。
Postman
不是浏览器。
没有:
txt
同源策略
所以:
txt
不会拦截
九、真正拦截的是谁
不是:
txt
Gin
也不是:
txt
Go
而是:
txt
浏览器
十、CORS 本质是什么
本质:
就是:
txt
后端告诉浏览器:
"我允许你跨域访问"
十一、浏览器怎么知道允不允许
因为:
后端:
会返回:
txt
响应头(Header)
十二、最重要响应头(必须记住)
txt
Access-Control-Allow-Origin
十三、什么意思
例如:
txt
Access-Control-Allow-Origin: *
表示:
txt
允许所有网站访问
十四、Gin 如何解决 CORS
最简单:
使用中间件。
十五、安装 cors 中间件
bash
go get github.com/gin-contrib/cors
十六、最简单写法(重点)
go
package main
import (
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
// 开启 CORS
r.Use(cors.Default())
r.GET("/hello", func(c *gin.Context) {
c.JSON(200, gin.H{
"msg": "hello",
})
})
r.Run(":8080")
}
十七、这里到底发生了什么
go
r.Use(cors.Default())
会自动:
给响应头加:
txt
Access-Control-Allow-Origin: *
于是:
浏览器:
发现:
txt
后端允许跨域
就不会拦截。
十八、完整请求流程(重点)
txt
前端 fetch
↓
浏览器发现跨域
↓
发送请求
↓
Gin 返回 Header
↓
Access-Control-Allow-Origin
↓
浏览器检查
↓
允许访问
十九、前端为什么能收到数据了
因为:
浏览器:
看到:
txt
后端允许跨域
所以:
不再阻止。
二十、CORS 是浏览器安全机制
一定记住:
txt
CORS 不是 Go 的规则
不是 Gin 的规则
不是 HTTP 的规则
它是:
txt
浏览器安全规则
二十一、什么是预检请求(重点)
很多时候:
你会发现:
txt
明明只发了一次请求
为什么后端收到两次?
这就是:
txt
预检请求(OPTIONS)
二十二、什么时候会触发预检
例如:
txt
PUT
DELETE
Authorization
application/json
这些:
可能触发:
txt
OPTIONS 请求
二十三、浏览器为什么要预检
浏览器:
会先问:
txt
"后端允许吗?"
二十四、流程图(重点)
txt
浏览器
↓
先发 OPTIONS
↓
后端返回允许
↓
浏览器再发真正请求
二十五、为什么后端必须处理 OPTIONS
否则:
浏览器:
会认为:
txt
不允许跨域
二十六、cors.Default() 帮你做了什么
它会自动:
1. 处理 OPTIONS
2. 添加允许跨域 Header
3. 设置默认规则
所以:
非常方便。
二十七、自定义 CORS(重点)
真实项目:
一般:
不会:
txt
允许所有网站
二十八、自定义允许域名
go
r.Use(cors.New(cors.Config{
AllowOrigins: []string{
"http://localhost:5173",
},
AllowMethods: []string{
"GET", "POST", "PUT", "DELETE",
},
AllowHeaders: []string{
"Origin", "Content-Type", "Authorization",
},
}))
二十九、AllowOrigins
表示:
txt
允许哪些前端访问
三十、AllowMethods
允许:
哪些 HTTP 方法。
三十一、AllowHeaders
允许:
哪些请求头。
例如:
txt
Authorization
JWT 登录:
经常会用。
三十二、JWT 为什么经常触发 CORS
因为:
JWT:
通常:
会带:
txt
Authorization
请求头。
于是:
浏览器:
会触发:
txt
预检 OPTIONS
三十三、为什么真实项目一定要配 CORS
因为:
前后端:
几乎:
都是分离的。
前端
txt
localhost:5173
后端
txt
localhost:8080
天然跨域。
三十四、最经典错误
1. 后端没开 CORS
浏览器直接拦截。
2. OPTIONS 没处理
预检失败。
3. Authorization 没允许
JWT 请求失败。
三十五、最后一句总结(必须记住)
CORS 本质:
txt
浏览器的跨域安全机制
核心思想:
txt
后端通过 Header 告诉浏览器:
"我允许你访问"
Gin 最简单解决方案:
go
r.Use(cors.Default())
真正核心流程:
txt
前端请求
↓
浏览器检查是否跨域
↓
后端返回允许跨域 Header
↓
浏览器决定是否放行