server-请求预检跨域问题
server-请求预检跨域问题
前篇
- 跨域问题服务端解决办法 - https://www.cnblogs.com/Im-Victor/p/15200864.html
- gin解决跨域问题 - https://blog.csdn.net/qq_43135259/article/details/125236412
- returns 404 - https://stackoverflow.com/questions/55347167/gin-contrib-cors-returns-404
前端业务发起一次跨域的 http 请求时, 如果设置有请求头如 Authorization
等校验的数据, 例如
1 | var xhr = new XMLHttpRequest(); |
浏览器实则会先发起两次请求, 一次时预检 (preflight) 请求 (OPTIONS 方法), 一次是业务正常的请求. 预检成功 (一般是返回 204 状态码) 时, 才会进行业务请求
服务器要对 预检 请求进行相应回应, 一般回应状态码 204, 不然会报错预检跨域失败
1 | Access to XMLHttpRequest at 'http://192.168.1.28:6353/recv/msg' from origin 'http://192.168.1.28:57090' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. |
实测
以 golang 的 gin 框架为例
有两种解决办法
对每个 handler 进行 OPTIONS 判断, 如果有则返回状态码 204, 推荐这种方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18func handlerCors() gin.HandlerFunc {
return func(c *gin.Context) {
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
c.Header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization, User-Token, User-Id, User-Uid")
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Cache-Control, Content-Language, Content-Type")
c.Header("Access-Control-Allow-Credentials", "false")
c.Header("Access-Control-Max-Age", "86400")
if c.Request.Method == "OPTIONS" { // 响应 204
c.AbortWithStatus(http.StatusNoContent)
}
c.Next()
}
}
router := gin.Default()
router.Use(handlerCors())使用另一个框架 cros:
go get github.com/gin-contrib/cors
1
2
3
4
5
6
7
8
9
10import "github.com/gin-contrib/cors"
router := gin.Default()
// 允许跨域请求
cfg := cors.DefaultConfig()
cfg.AddAllowHeaders("Authorization")
cfg.AllowCredentials = true
cfg.AllowAllOrigins = false
cfg.AllowOriginFunc = func(origin string) bool { return true } // 跨域检验
router.Use(cors.New(cfg))
踩坑
未设置跨域
报错:
Access to XMLHttpRequest at 'https://xxx' from origin 'https://ccc' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
可能得原因请求的
Content-Type
设置错误1
2
3
4
5var xhr = new XMLHttpRequest();
//xhr.setRequestHeader('Content-Type', 'application/json;charset=utf-8')
// 修改为
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");