Gin 跨域中间件配置
浏览器同源策略限制跨域请求,前后端分离部署时需要后端返回 CORS 响应头。这里提供两个 Gin 中间件:一个按白名单放行,一个放行所有来源。
方式一:白名单校验(推荐)
只有 originDomains 中配置的来源才允许跨域:
1package handler
2
3import (
4 "github.com/gin-gonic/gin"
5 "net/http"
6)
7
8func Cors() gin.HandlerFunc {
9 return func(c *gin.Context) {
10 method := c.Request.Method // 请求方法
11 origin := c.Request.Header.Get("Origin") // 请求头部
12 originDomains := []string{"http://localhost:3000"}
13 inArraysFlag := false
14 for _, value := range originDomains {
15 if origin == value {
16 inArraysFlag = true
17 break
18 }
19 }
20 if origin != "" && inArraysFlag {
21 // 只允许白名单内的来源跨域访问
22 c.Header("Access-Control-Allow-Origin", origin)
23 // 服务器支持的所有跨域请求的方法,为了避免浏览器多次发起"预检"请求
24 c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
25 // 允许的请求头类型
26 c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,X_Requested_With,Accept, Origin, Host, Connection, Accept-Encoding, Accept-Language,DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Pragma")
27 // 允许浏览器读取的自定义响应头
28 c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma,FooBar")
29 // 预检结果的缓存时间,单位为秒,避免重复发起预检请求
30 c.Header("Access-Control-Max-Age", "172800")
31 // 跨域请求是否需要携带 cookie 信息
32 c.Header("Access-Control-Allow-Credentials", "false")
33 c.Set("content-type", "application/json")
34 }
35 // 放行所有 OPTIONS 预检请求
36 if method == "OPTIONS" {
37 c.JSON(http.StatusOK, "Options Request!")
38 }
39 // 处理请求
40 c.Next()
41 }
42}
方式二:放行所有来源
内网环境或调试时可以使用更宽松的版本,直接回显请求的 Origin:
1func CorsHandler() gin.HandlerFunc {
2 return func(c *gin.Context) {
3 method := c.Request.Method
4 origin := c.Request.Header.Get("Origin")
5 if origin != "" {
6 c.Header("Access-Control-Allow-Origin", origin)
7 c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
8 c.Header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization")
9 c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Cache-Control, Content-Language, Content-Type")
10 c.Header("Access-Control-Allow-Credentials", "false")
11 c.Set("content-type", "application/json")
12 }
13 if method == "OPTIONS" {
14 c.AbortWithStatus(http.StatusNoContent)
15 }
16 c.Next()
17 }
18}
使用时挂在路由上即可:
1r := gin.Default()
2r.Use(Cors())
注意:Access-Control-Allow-Origin 设为 * 时不能同时开启 Allow-Credentials,需要携带 cookie 的场景要像方式一那样回显具体 Origin。
