CORS 中间件
CORS (Cross-Origin Resource Sharing) 中间件用于处理跨域资源共享,允许您控制哪些域可以访问您的 API 资源。
使用方法
基础用法
import ( "go-slim.dev/slim" "go-slim.dev/slim/middleware")func main() { s := slim.New() // 使用默认配置 s.Use(middleware.CORS()) s.GET("/api/users", func(c slim.Context) error { return c.JSON(200, map[string]string{"message": "Hello"}) }) s.Start(":8080")}自定义配置
s := slim.New()s.Use(middleware.CORSWithConfig(middleware.CORSConfig{ AllowOrigins: []string{"https://example.com", "https://app.example.com"}, AllowMethods: []string{"GET", "POST", "PUT", "DELETE"}, AllowHeaders: []string{"Content-Type", "Authorization"}, AllowCredentials: true, ExposeHeaders: []string{"X-Request-ID"}, MaxAge: 3600,}))配置选项
CORSConfig
type CORSConfig struct { // AllowOrigins 定义允许访问资源的源列表 // 可选。默认值 []string{"*"} AllowOrigins []string // AllowOriginFunc 是一个自定义函数,用于验证源 // 如果设置此选项,AllowOrigins 将被忽略 // 可选 AllowOriginFunc func(origin string) (bool, error) // AllowMethods 定义访问资源时允许的 HTTP 方法列表 // 用于响应预检请求 // 可选。默认值包含常用方法 AllowMethods []string // AllowHeaders 定义实际请求中可以使用的请求头列表 // 用于响应预检请求 // 可选。默认值 []string{} AllowHeaders []string // AllowCredentials 指示当凭证标志为 true 时, // 是否可以暴露对请求的响应 // 可选。默认值 false AllowCredentials bool // ExposeHeaders 定义客户端允许访问的响应头白名单 // 可选。默认值 []string{} ExposeHeaders []string // MaxAge 指示预检请求的结果可以被缓存多长时间(秒) // 可选。默认值 0 MaxAge int}使用示例
1. 允许所有源(开发环境)
s.Use(middleware.CORS())默认配置允许所有源访问(AllowOrigins: []string{"*"}),适合开发环境。
2. 限制特定域名
s.Use(middleware.CORSWithConfig(middleware.CORSConfig{ AllowOrigins: []string{ "https://example.com", "https://app.example.com", },}))3. 使用通配符模式
s.Use(middleware.CORSWithConfig(middleware.CORSConfig{ AllowOrigins: []string{ "https://*.example.com", // 允许所有 example.com 的子域名 "http://localhost:*", // 允许 localhost 的所有端口 },}))4. 自定义源验证函数
s.Use(middleware.CORSWithConfig(middleware.CORSConfig{ AllowOriginFunc: func(origin string) (bool, error) { // 自定义逻辑,例如从数据库查询 allowedOrigins := []string{ "https://example.com", "https://app.example.com", } for _, allowed := range allowedOrigins { if origin == allowed { return true, nil } } return false, nil },}))5. 支持凭证(Cookie)
s.Use(middleware.CORSWithConfig(middleware.CORSConfig{ AllowOrigins: []string{"https://example.com"}, AllowCredentials: true, AllowHeaders: []string{"Content-Type", "Authorization"},}))注意:当 AllowCredentials: true 时,AllowOrigins 不能设置为 ["*"],必须指定具体的域名。
6. 完整配置示例
s.Use(middleware.CORSWithConfig(middleware.CORSConfig{ AllowOrigins: []string{ "https://example.com", "https://app.example.com", }, AllowMethods: []string{ "GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", }, AllowHeaders: []string{ "Origin", "Content-Type", "Accept", "Authorization", "X-Request-ID", }, ExposeHeaders: []string{ "X-Request-ID", "X-Response-Time", }, AllowCredentials: true, MaxAge: 3600, // 1 小时}))工作原理
简单请求
对于简单请求(Simple Request),CORS 中间件会:
- 检查请求的
Origin头 - 验证源是否在允许列表中
- 如果允许,设置
Access-Control-Allow-Origin响应头 - 如果配置了
AllowCredentials,设置相应的响应头 - 继续处理请求
预检请求
对于预检请求(Preflight Request,HTTP OPTIONS),CORS 中间件会:
- 检查请求的
Origin头 - 验证源是否在允许列表中
- 设置
Access-Control-Allow-Origin - 设置
Access-Control-Allow-Methods - 设置
Access-Control-Allow-Headers - 如果配置了
MaxAge,设置Access-Control-Max-Age - 返回
204 No Content状态码
默认配置
CORSConfig{ AllowOrigins: []string{"*"}, AllowMethods: []string{ "GET", "HEAD", "PUT", "PATCH", "POST", "DELETE", }, AllowHeaders: []string{}, AllowCredentials: false, ExposeHeaders: []string{}, MaxAge: 0,}最佳实践
1. 生产环境限制源
// 开发环境if os.Getenv("ENV") == "development" { s.Use(middleware.CORS())} else { // 生产环境 s.Use(middleware.CORSWithConfig(middleware.CORSConfig{ AllowOrigins: []string{ "https://yourdomain.com", "https://app.yourdomain.com", }, AllowCredentials: true, }))}2. 使用环境变量配置
allowedOrigins := strings.Split(os.Getenv("ALLOWED_ORIGINS"), ",")s.Use(middleware.CORSWithConfig(middleware.CORSConfig{ AllowOrigins: allowedOrigins,}))3. 限制暴露的响应头
只暴露客户端真正需要的响应头:
s.Use(middleware.CORSWithConfig(middleware.CORSConfig{ ExposeHeaders: []string{ "X-Request-ID", "X-Total-Count", // 分页时可能需要 },}))4. 合理设置 MaxAge
设置合理的缓存时间可以减少预检请求的数量:
s.Use(middleware.CORSWithConfig(middleware.CORSConfig{ MaxAge: 86400, // 24 小时}))安全考虑
-
不要在生产环境使用
AllowOrigins: ["*"],这会允许任何网站访问您的 API -
谨慎使用
AllowCredentials: true,确保您了解其安全影响 -
限制
AllowMethods,只允许必要的 HTTP 方法 -
限制
AllowHeaders,只允许必要的请求头 -
使用 HTTPS,避免在不安全的连接上传输敏感信息
常见问题
Q: 为什么 CORS 请求失败?
A: 检查以下几点:
- 服务器是否正确配置了 CORS 中间件
AllowOrigins是否包含客户端的域名- 如果使用凭证(Cookie),是否设置了
AllowCredentials: true - 是否正确设置了
AllowHeaders和AllowMethods
Q: 什么是预检请求?
A: 预检请求是浏览器在发送某些跨域请求前自动发送的 OPTIONS 请求,用于检查服务器是否允许实际请求。
Q: AllowOrigins: ["*"] 和 AllowCredentials: true 能同时使用吗?
A: 不能。出于安全考虑,当启用凭证时,必须指定具体的源,不能使用通配符 *。