Gin 框架 CORS 策略笔记

什么是 CORS

CORS(跨域资源共享)是浏览器的一种安全机制,用于限制一个网页从不同的域请求资源。默认情况下,浏览器会阻止跨域请求,除非服务器明确允许跨域访问。

在使用 Gin 框架开发 API 时,如果前端页面和后端 API 不在同一个域或端口下,就需要配置 CORS 以解决跨域问题。


Gin 中处理 CORS 的方法

1. 使用 github.com/gin-contrib/cors 中间件

Gin 提供了一个官方推荐的 CORS 中间件,可以通过简单配置实现跨域支持。

安装中间件

go get github.com/gin-contrib/cors

示例代码

package main

import (
    "github.com/gin-contrib/cors"
    "github.com/gin-gonic/gin"
    "time"
)

func main() {
    r := gin.Default()

    // 配置 CORS 中间件
    r.Use(cors.New(cors.Config{
        AllowOrigins:     []string{"http://example.com", "http://localhost:3000"}, // 允许的源
        AllowMethods:     []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},     // 允许的方法
        AllowHeaders:     []string{"Origin", "Content-Type", "Authorization"},    // 允许的头
        ExposeHeaders:    []string{"Content-Length"},                              // 可见的头
        AllowCredentials: true,                                                   // 允许携带凭据
        MaxAge:           12 * time.Hour,                                         // 缓存时间
    }))

    // 示例路由
    r.GET("/api/test", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "CORS is configured!",
        })
    })

    // 启动服务
    r.Run(":8080")
}

2. 手动设置 CORS Headers

如果不想使用第三方中间件,可以手动设置跨域响应头。

示例代码

package main

import (
    "github.com/gin-gonic/gin"
    "net/http"
)

func main() {
    r := gin.Default()

    // 自定义中间件处理 CORS
    r.Use(func(c *gin.Context) {
        c.Writer.Header().Set("Access-Control-Allow-Origin", "*") // 允许所有域
        c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
        c.Writer.Header().Set("Access-Control-Allow-Headers", "Origin, Content-Type, Authorization")
        c.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Length")
        c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")

        if c.Request.Method == "OPTIONS" {
            c.AbortWithStatus(http.StatusNoContent)
            return
        }
        c.Next()
    })

    // 示例路由
    r.GET("/api/test", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "CORS is configured manually!",
        })
    })

    r.Run(":8080")
}

配置选项说明

1. AllowOrigins

  • 含义:允许的请求来源列表。
  • 类型[]string
  • 示例

    AllowOrigins: []string{"http://example.com", "http://localhost:3000"}
  • 注意

    • 不建议在生产环境中使用通配符 *,除非非常确定不需要限制来源。

2. AllowMethods

  • 含义:允许的 HTTP 方法。
  • 类型[]string
  • 示例

    AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}

3. AllowHeaders

  • 含义:允许的请求头。
  • 类型[]string
  • 示例

    AllowHeaders: []string{"Origin", "Content-Type", "Authorization"}
  • 说明

    • 如果前端发送请求包含自定义头,必须在这里显式允许,否则会被浏览器拦截。

4. ExposeHeaders

  • 含义:允许前端访问的响应头。
  • 类型[]string
  • 示例

    ExposeHeaders: []string{"Content-Length"}

5. AllowCredentials

  • 含义:是否允许跨域请求携带凭据(如 Cookies)。
  • 类型bool
  • 示例

    AllowCredentials: true

6. MaxAge

  • 含义:预检请求的缓存时间。
  • 类型time.Duration
  • 示例

    MaxAge: 12 * time.Hour

注意事项

  1. 开发环境配置宽松:可以使用通配符 * 允许所有来源和头,以方便调试。
  2. 生产环境配置严格:仅允许特定的域名、方法和头,以减少安全风险。
  3. OPTIONS 请求

    • 浏览器会在某些情况下(如非简单请求)自动发送预检请求(OPTIONS)。
    • 需要处理好预检请求并返回正确的跨域响应头。
  4. 安全性

    • 不随意允许所有来源(*)。
    • 避免在生产中启用 AllowCredentials* 的组合,可能导致安全问题。

常见问题

1. 为什么前端仍然报跨域错误?

  • 可能是 CORS 配置不正确,特别是 AllowOriginsAllowHeaders
  • 检查是否正确返回了 Access-Control-Allow-Origin 和其他相关头。

2. 如何调试跨域问题?

  • 使用浏览器开发者工具查看请求和响应头,确认是否包含正确的 CORS 头。
  • 在后端日志中检查是否正确处理了 OPTIONS 请求。

3. 通配符 * 和携带凭据的限制

  • 如果 AllowCredentials 设置为 true,则 AllowOrigins 不能是 *,必须指定具体的域名。

通过以上配置和说明,你可以在 Gin 框架中灵活处理跨域问题。如果有特殊需求,可以进一步调整设置。

每日更新-免费小火箭账号
不要错过任何机会,探索最新的应用和游戏,就在我们的平台。
立即访问
最后修改:2024 年 12 月 31 日
如果觉得我的文章对你有用,请随意赞赏