CORS跨域 #

一、CORS概述 #

1.1 什么是CORS #

CORS(Cross-Origin Resource Sharing)是一种机制,允许Web应用从不同域访问资源。

1.2 为什么需要CORS #

浏览器的同源策略限制了跨域请求,CORS允许服务器声明哪些源可以访问资源。

二、基本配置 #

2.1 使用内置中间件 #

go
package main

import (
    "github.com/gofiber/fiber/v2"
    "github.com/gofiber/fiber/v2/middleware/cors"
)

func main() {
    app := fiber.New()
    
    // 默认配置(允许所有来源)
    app.Use(cors.New())
    
    app.Get("/", func(c *fiber.Ctx) error {
        return c.JSON(fiber.Map{"message": "Hello"})
    })
    
    app.Listen(":3000")
}

2.2 自定义配置 #

go
app.Use(cors.New(cors.Config{
    AllowOrigins: "https://example.com, https://api.example.com",
    AllowMethods: "GET,POST,PUT,DELETE,OPTIONS",
    AllowHeaders: "Content-Type,Authorization",
}))

三、完整配置 #

3.1 所有配置选项 #

go
app.Use(cors.New(cors.Config{
    // 允许的来源
    AllowOrigins: "https://example.com",
    
    // 允许的方法
    AllowMethods: "GET,POST,PUT,DELETE,OPTIONS",
    
    // 允许的请求头
    AllowHeaders: "Content-Type,Authorization,X-Requested-With",
    
    // 允许携带凭证
    AllowCredentials: true,
    
    // 暴露的响应头
    ExposeHeaders: "Content-Length,Content-Type",
    
    // 预检请求缓存时间
    MaxAge: 86400,
}))

3.2 允许所有来源 #

go
app.Use(cors.New(cors.Config{
    AllowOrigins: "*",
    AllowMethods: "GET,POST,PUT,DELETE,OPTIONS",
    AllowHeaders: "Content-Type,Authorization",
}))

3.3 允许多个来源 #

go
app.Use(cors.New(cors.Config{
    AllowOrigins: "https://example.com, https://app.example.com, http://localhost:3000",
    AllowMethods: "GET,POST,PUT,DELETE",
    AllowHeaders: "Content-Type,Authorization",
    AllowCredentials: true,
}))

四、动态来源 #

4.1 动态验证来源 #

go
app.Use(cors.New(cors.Config{
    AllowOriginsFunc: func(origin string) bool {
        // 允许所有子域名
        return strings.HasSuffix(origin, ".example.com") ||
               origin == "http://localhost:3000"
    },
    AllowMethods: "GET,POST,PUT,DELETE",
}))

4.2 白名单验证 #

go
var allowedOrigins = map[string]bool{
    "https://example.com":      true,
    "https://app.example.com":  true,
    "http://localhost:3000":    true,
    "http://localhost:8080":    true,
}

app.Use(cors.New(cors.Config{
    AllowOriginsFunc: func(origin string) bool {
        return allowedOrigins[origin]
    },
    AllowMethods: "GET,POST,PUT,DELETE",
    AllowCredentials: true,
}))

五、自定义CORS中间件 #

5.1 手动实现 #

go
func CORSMiddleware() fiber.Handler {
    return func(c *fiber.Ctx) error {
        origin := c.Get("Origin")
        
        // 设置CORS头
        c.Set("Access-Control-Allow-Origin", origin)
        c.Set("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS")
        c.Set("Access-Control-Allow-Headers", "Content-Type,Authorization")
        c.Set("Access-Control-Allow-Credentials", "true")
        
        // 处理预检请求
        if c.Method() == "OPTIONS" {
            return c.SendStatus(204)
        }
        
        return c.Next()
    }
}

5.2 带验证的CORS #

go
func SecureCORS(allowedOrigins []string) fiber.Handler {
    return func(c *fiber.Ctx) error {
        origin := c.Get("Origin")
        
        // 验证来源
        allowed := false
        for _, o := range allowedOrigins {
            if o == origin || o == "*" {
                allowed = true
                break
            }
        }
        
        if allowed {
            c.Set("Access-Control-Allow-Origin", origin)
            c.Set("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS")
            c.Set("Access-Control-Allow-Headers", "Content-Type,Authorization")
            c.Set("Access-Control-Allow-Credentials", "true")
            c.Set("Access-Control-Max-Age", "86400")
        }
        
        if c.Method() == "OPTIONS" {
            return c.SendStatus(204)
        }
        
        return c.Next()
    }
}

六、常见问题 #

6.1 预检请求失败 #

go
// 确保处理OPTIONS请求
app.Use(cors.New(cors.Config{
    AllowOrigins: "*",
    AllowMethods: "GET,POST,PUT,DELETE,OPTIONS",
    AllowHeaders: "Content-Type,Authorization",
}))

// 或手动处理
app.Options("/*", func(c *fiber.Ctx) error {
    return c.SendStatus(204)
})

6.2 凭证问题 #

go
// AllowCredentials为true时,AllowOrigins不能为"*"
app.Use(cors.New(cors.Config{
    AllowOrigins:     "https://example.com",
    AllowCredentials: true,
}))

七、总结 #

7.1 CORS配置要点 #

配置 说明
AllowOrigins 允许的来源
AllowMethods 允许的方法
AllowHeaders 允许的请求头
AllowCredentials 允许凭证
MaxAge 预检缓存时间

7.2 下一步 #

现在你已经掌握了CORS跨域,接下来让我们学习 WebSocket,了解实时通信!

最后更新:2026-03-28