CORS
CORS(跨域资源共享)是 Fiber 的一个中间件,允许服务器指定谁可以访问其资源以及如何访问。它不是一个安全特性,而是放宽 Web 浏览器针对跨域请求的安全模型的一种方式。您可以在 Mozilla Developer Network 上了解更多关于 CORS 的信息。
这个中间件通过在您的 Fiber 应用程序的响应中添加 CORS 头部来工作。这些头部指定了哪些源、方法和头部允许用于跨域请求。它还处理预检请求,这是一种 CORS 机制,用于检查实际请求是否可以安全发送。
中间件使用 AllowOrigins
选项来控制哪些源可以发起跨域请求。它支持单个源、多个源、子域匹配和通配符源。它还允许使用 AllowOriginsFunc
选项进行程序化源验证。
为了确保提供的 AllowOrigins
源格式正确,这个中间件会验证并规范化它们。它会检查有效的方案,例如 HTTP 或 HTTPS,并且会自动移除尾部斜杠。如果提供的源无效,中间件将引发 panic。
配置 CORS 时,重要的是要避免 常见陷阱,例如将通配符源与凭据一起使用、对源过于宽松,以及 AllowOriginsFunc
验证不足。错误配置可能会使您的应用程序面临各种安全风险。
签名
func New(config ...Config) fiber.Handler
示例
导入属于 Fiber web 框架一部分的中间件包
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cors"
)
在您初始化 Fiber app 后,您可以使用以下方式
基本用法
要使用默认配置,只需使用 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
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 | string | AllowOrigins 定义了一个逗号分隔的源列表,这些源可以访问资源。这支持子域匹配,因此您可以使用诸如 "https://*.example.com" 之类的值来允许 example.com 的任何子域提交请求。 | "*" |
AllowMethods | string | AllowMethods 定义了一个允许访问资源时使用的方法列表。这用于响应预检请求。 | "GET,POST,HEAD,PUT,DELETE,PATCH" |
AllowHeaders | string | AllowHeaders 定义了一个请求头部列表,可在进行实际请求时使用。这用于响应预检请求。 | "" |
AllowCredentials | bool | AllowCredentials 指示当凭据标志为 true 时,是否可以暴露对请求的响应。当作为预检请求响应的一部分使用时,这指示是否可以使用凭据进行实际请求。注意:如果设置为 true,AllowOrigins 不能设置为通配符 ("*" ),以防止安全漏洞。 | false |
ExposeHeaders | string | ExposeHeaders 定义了允许客户端访问的白名单头部。 | "" |
MaxAge | int | 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 配置的关键在于具体性和谨慎性。通过仔细选择允许哪些源、方法和头部,您可以帮助保护您的应用程序免受跨域攻击。