CORS
CORS(跨源资源共享)是 Fiber 的一个中间件,允许服务器指定谁可以访问其资源以及如何访问。它不是一个安全特性,而是一种放宽跨源请求的 Web 浏览器安全模型的方法。您可以在 Mozilla Developer Network 上了解有关 CORS 的更多信息。
此中间件通过向 Fiber 应用程序的响应中添加 CORS 头来工作。这些头指定哪些来源、方法和头允许跨源请求。它还处理预检请求,这是 CORS 机制,用于检查实际请求是否安全发送。
该中间件使用 AllowOrigins
选项来控制哪些来源可以进行跨源请求。它支持单个来源、多个来源、子域匹配和通配符来源。它还允许使用 AllowOriginsFunc
选项进行编程来源验证。
为了确保提供的 AllowOrigins
来源格式正确,此中间件会对其进行验证和规范化。它检查有效方案,即 HTTP 或 HTTPS,并将自动删除尾部斜杠。如果提供的来源无效,中间件将恐慌。
在配置 CORS 时,重要的是避免 常见陷阱,例如对凭据使用通配符来源、对来源过于宽松以及使用 AllowOriginsFunc
进行不充分的验证。错误配置可能会使您的应用程序面临各种安全风险。
签名
func New(config ...Config) fiber.Handler
示例
导入 Fiber Web 框架中包含的中间件包
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cors"
)
在启动 Fiber 应用程序后,您可以使用以下可能性
基本用法
要使用默认配置,只需使用 cors.New()
。这将允许通配符来源“*”、所有方法、无凭据,并且没有头或公开头。
app.Use(cors.New())
自定义配置(特定来源、头等)
// Initialize default config
app.Use(cors.New())
// Or extend your config for customization
app.Use(cors.New(cors.Config{
AllowOrigins: "https://fiber.org.cn, https://gofiber.net",
AllowHeaders: "Origin, Content-Type, Accept",
}))
动态来源验证
您可以使用 AllowOriginsFunc
根据其来源以编程方式确定是否允许请求。当您需要根据数据库或其他动态来源验证来源时,这非常有用。如果允许来源,该函数应返回 true
,否则返回 false
。
使用 AllowOriginsFunc
时,请务必查看 安全注意事项。
切勿允许 AllowOriginsFunc
对所有来源返回 true
。当 AllowCredentials
设置为 true
时,这一点尤其重要。这样做可以绕过使用通配符来源和凭据的限制,使您的应用程序面临严重的安全性威胁。
如果您需要允许通配符来源,请使用带通配符 "*"
的 AllowOrigins
,而不是 AllowOriginsFunc
。
// dbCheckOrigin checks if the origin is in the list of allowed origins in the database.
func dbCheckOrigin(db *sql.DB, origin string) bool {
// Placeholder query - adjust according to your database schema and query needs
query := "SELECT COUNT(*) FROM allowed_origins WHERE origin = $1"
var count int
err := db.QueryRow(query, origin).Scan(&count)
if err != nil {
// Handle error (e.g., log it); for simplicity, we return false here
return false
}
return count > 0
}
// ...
app.Use(cors.New(cors.Config{
AllowOriginsFunc: func(origin string) bool {
return dbCheckOrigin(db, origin)
},
}))
禁止使用
以下示例被禁止,因为它会使您的应用程序面临安全风险。它将 AllowOrigins
设置为 "*"
(通配符)并将 AllowCredentials
设置为 true
。
app.Use(cors.New(cors.Config{
AllowOrigins: "*",
AllowCredentials: true,
}))
这将导致以下恐慌
panic: [CORS] 'AllowCredentials' is true, but 'AllowOrigins' cannot be set to `"*"`.
配置
属性 | 类型 | 描述 | 默认值 |
---|---|---|---|
下一步 | func(*fiber.Ctx) bool | Next 定义了一个函数,当返回 true 时跳过此中间件。 | nil |
AllowOriginsFunc | func(origin string) bool | AllowOriginsFunc 是一个函数,它根据请求的来源动态确定是否允许请求。如果此函数返回 true ,则“Access-Control-Allow-Origin”响应头将设置为请求的“origin”头。仅当请求的来源与 AllowOrigins 中的任何来源不匹配时才使用此函数。 | nil |
AllowOrigins | 字符串 | AllowOrigins 定义了一个逗号分隔的源列表,这些源可以访问资源。这支持子域匹配,因此你可以使用诸如“https://*.example.com”的值来允许 example.com 的任何子域提交请求。 | "*" |
AllowMethods | 字符串 | AllowMethods 定义了访问资源时允许使用的方法列表。这是用来响应预检请求的。 | “GET,POST,HEAD,PUT,DELETE,PATCH” |
AllowHeaders | 字符串 | AllowHeaders 定义了在进行实际请求时可以使用的请求头列表。这是用来响应预检请求的。 | "" |
AllowCredentials | 布尔值 | AllowCredentials 指示当凭据标志为 true 时是否可以公开对请求的响应。当用作对预检请求的响应的一部分时,这表示是否可以使用凭据进行实际请求。注意:如果为 true,则 AllowOrigins 不能设置为通配符 ("*" ) 以防止安全漏洞。 | false |
ExposeHeaders | 字符串 | ExposeHeaders 定义了客户端允许访问的白名单头。 | "" |
MaxAge | 整数 | MaxAge 指示预检请求的结果可以缓存多长时间(以秒为单位)。如果你传递 MaxAge 0,则不会添加 Access-Control-Max-Age 头,并且浏览器默认使用 5 秒。要完全禁用缓存,请传递 MaxAge 值为负数。它将把 Access-Control-Max-Age 头设置为 0。 | 0 |
默认配置
var ConfigDefault = Config{
Next: nil,
AllowOriginsFunc: nil,
AllowOrigins: "*",
AllowMethods: strings.Join([]string{
fiber.MethodGet,
fiber.MethodPost,
fiber.MethodHead,
fiber.MethodPut,
fiber.MethodDelete,
fiber.MethodPatch,
}, ","),
AllowHeaders: "",
AllowCredentials: false,
ExposeHeaders: "",
MaxAge: 0,
}
子域匹配
AllowOrigins
配置支持匹配任何级别的子域。这意味着你可以使用诸如 "https://*.example.com"
的值来允许 example.com
的任何子域提交请求,包括多个子域级别,例如 "https://sub.sub.example.com"
。
示例
如果你想允许来自 example.com
的任何子域(包括嵌套子域)的 CORS 请求,你可以像这样配置 AllowOrigins
app.Use(cors.New(cors.Config{
AllowOrigins: "https://*.example.com",
}))
工作原理
CORS 中间件通过向 Fiber 应用程序的响应中添加必要的 CORS 头来工作。这些头告诉浏览器哪些源、方法和头允许跨域请求。
当一个请求进来时,中间件首先检查它是否是一个预检请求,这是一个 CORS 机制,用于确定实际请求是否安全发送。预检请求是具有特定 CORS 头的 HTTP OPTIONS 请求。如果它是一个预检请求,则中间件会使用适当的 CORS 头响应并结束请求。
如果不是预检请求,则中间件会将 CORS 头添加到响应中并将请求传递到下一个处理程序。添加的实际 CORS 头取决于中间件的配置。
AllowOrigins
选项控制哪些源可以进行跨域请求。中间件处理不同的 AllowOrigins
配置如下
-
单一来源:如果
AllowOrigins
设置为单一来源,例如"http://www.example.com"
,并且该来源与传入请求的来源匹配,则中间件会将标头Access-Control-Allow-Origin: http://www.example.com
添加到响应中。 -
多个来源:如果
AllowOrigins
设置为多个来源,例如"https://example.com, https://www.example.com"
,则中间件会选择与传入请求的来源匹配的来源。 -
子域名匹配:如果
AllowOrigins
包含"https://*.example.com"
,则会匹配https://sub.example.com
等子域名,并且"https://sub.example.com"
将成为标头。这也将匹配https://sub.sub.example.com
等,但不会匹配https://example.com
。 -
通配符来源:如果
AllowOrigins
设置为"*"
,则中间件会使用它并将标头Access-Control-Allow-Origin: *
添加到响应中。
在以上所有情况下,除了通配符来源之外,中间件要么将 Access-Control-Allow-Origin
标头添加到与传入请求的来源匹配的响应中,要么根本不会添加该标头(如果来源不被允许)。
- 以编程方式验证来源::中间件还处理
AllowOriginsFunc
选项,该选项允许您以编程方式确定是否允许某个来源。如果AllowOriginsFunc
为某个来源返回true
,则中间件会将Access-Control-Allow-Origin
标头设置为该来源。
AllowMethods
选项控制允许哪些 HTTP 方法。例如,如果 AllowMethods
设置为 "GET, POST"
,则中间件会将标头 Access-Control-Allow-Methods: GET, POST
添加到响应中。
AllowHeaders
选项指定实际请求中允许哪些标头。中间件将 Access-Control-Allow-Headers 响应标头设置为 AllowHeaders
的值。这会告知客户端它可以在实际请求中使用哪些标头。
AllowCredentials
选项指示是否可以在凭据标志为 true 时公开对请求的响应。如果 AllowCredentials
设置为 true
,则中间件会将标头 Access-Control-Allow-Credentials: true
添加到响应中。为了防止安全漏洞,如果 AllowOrigins
设置为通配符 (*
),则无法将 AllowCredentials
设置为 true
。
ExposeHeaders
选项定义了客户端允许访问的标头白名单。如果 ExposeHeaders
设置为 "X-Custom-Header"
,则中间件会将标头 Access-Control-Expose-Headers: X-Custom-Header
添加到响应中。
MaxAge
选项指示预检请求的结果可以缓存多长时间。如果 MaxAge
设置为 3600
,则中间件会将标头 Access-Control-Max-Age: 3600
添加到响应中。
此中间件中使用 Vary
标头告知客户端服务器对请求的响应。对于预检请求和实际请求,Vary 标头都设置为 Access-Control-Request-Method
和 Access-Control-Request-Headers
。对于预检请求,Vary 标头还设置为 Origin
。Vary
标头对于缓存非常重要。它帮助缓存(例如 Web 浏览器的缓存或 CDN)确定何时可以在响应未来请求时使用缓存的响应,以及何时需要向服务器查询新响应。
安全注意事项
配置 CORS 时,错误配置可能会让您的应用程序面临各种安全风险。以下是避免的一些安全配置和常见陷阱
安全配置
-
指定允许的来源:不要使用通配符 (
"*"
),而应指定允许进行请求的确切域名。例如,AllowOrigins: "https://www.example.com, https://api.example.com"
确保只有这些域名可以向您的应用程序发出跨源请求。 -
小心使用凭据:如果您的应用程序需要在跨源请求中支持凭据,请确保将
AllowCredentials
设置为true
,并在AllowOrigins
中指定确切的来源。在这种情况下,不要使用通配符来源。 -
限制公开的标头:仅通过适当设置
ExposeHeaders
将客户端应用程序必需的标头列入白名单。这可以最大程度地降低公开敏感信息的风险。
常见陷阱
-
带有凭据的通配符来源:将
AllowOrigins
设置为"*"
(通配符)并将AllowCredentials
设置为true
是常见的错误配置。禁止这种组合,因为它会让您的应用程序面临安全风险。 -
过于宽松的来源:指定过多的来源或使用过于宽泛的模式(例如,
https://*.example.com
)可能会无意中允许恶意网站与您的应用程序交互。在允许的来源方面尽可能具体。 -
不充分的
AllowOriginsFunc
验证:在使用AllowOriginsFunc
进行动态来源验证时,请确保该函数包含可靠的检查,以防止接受未经授权的来源。过于宽松的验证会导致安全漏洞。切勿允许AllowOriginsFunc
对所有来源返回true
。当AllowCredentials
设置为true
时,这一点尤其重要。这样做会绕过使用带有凭据的通配符来源的限制,从而让您的应用程序面临严重的安全性威胁。如果您需要允许通配符来源,请使用带有通配符"*"
的AllowOrigins
,而不是AllowOriginsFunc
。
请记住,安全 CORS 配置的关键在于具体性和谨慎。通过仔细选择允许哪些来源、方法和标头,您可以帮助保护您的应用程序免受跨源攻击。