跳至主要内容
版本:v2.x

Keyauth

Key auth 中间件提供基于密钥的身份验证。

签名

func New(config ...Config) fiber.Handler

示例

package main

import (
"crypto/sha256"
"crypto/subtle"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/keyauth"
)

var (
apiKey = "correct horse battery staple"
)

func validateAPIKey(c *fiber.Ctx, key string) (bool, error) {
hashedAPIKey := sha256.Sum256([]byte(apiKey))
hashedKey := sha256.Sum256([]byte(key))

if subtle.ConstantTimeCompare(hashedAPIKey[:], hashedKey[:]) == 1 {
return true, nil
}
return false, keyauth.ErrMissingOrMalformedAPIKey
}

func main() {
app := fiber.New()

// note that the keyauth middleware needs to be defined before the routes are defined!
app.Use(keyauth.New(keyauth.Config{
KeyLookup: "cookie:access_token",
Validator: validateAPIKey,
}))

app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Successfully authenticated!")
})

app.Listen(":3000")
}

测试

# No api-key specified -> 400 missing 
curl https://127.0.0.1:3000
#> missing or malformed API Key

curl --cookie "access_token=correct horse battery staple" https://127.0.0.1:3000
#> Successfully authenticated!

curl --cookie "access_token=Clearly A Wrong Key" https://127.0.0.1:3000
#> missing or malformed API Key

有关更详细的示例,另请参阅 github.com/gofiber/recipes 存储库,特别是 fiber-envoy-extauthz 存储库和 keyauth 示例 代码。

仅对某些端点进行身份验证

如果你只想对某些端点进行身份验证,则可以使用 keyauth 的 Config 并应用过滤器函数(例如 authFilter),如下所示

package main

import (
"crypto/sha256"
"crypto/subtle"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/keyauth"
"regexp"
"strings"
)

var (
apiKey = "correct horse battery staple"
protectedURLs = []*regexp.Regexp{
regexp.MustCompile("^/authenticated$"),
regexp.MustCompile("^/auth2$"),
}
)

func validateAPIKey(c *fiber.Ctx, key string) (bool, error) {
hashedAPIKey := sha256.Sum256([]byte(apiKey))
hashedKey := sha256.Sum256([]byte(key))

if subtle.ConstantTimeCompare(hashedAPIKey[:], hashedKey[:]) == 1 {
return true, nil
}
return false, keyauth.ErrMissingOrMalformedAPIKey
}

func authFilter(c *fiber.Ctx) bool {
originalURL := strings.ToLower(c.OriginalURL())

for _, pattern := range protectedURLs {
if pattern.MatchString(originalURL) {
return false
}
}
return true
}

func main() {
app := fiber.New()

app.Use(keyauth.New(keyauth.Config{
Next: authFilter,
KeyLookup: "cookie:access_token",
Validator: validateAPIKey,
}))

app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Welcome")
})
app.Get("/authenticated", func(c *fiber.Ctx) error {
return c.SendString("Successfully authenticated!")
})
app.Get("/auth2", func(c *fiber.Ctx) error {
return c.SendString("Successfully authenticated 2!")
})

app.Listen(":3000")
}

这将导致

# / does not need to be authenticated
curl https://127.0.0.1:3000
#> Welcome

# /authenticated needs to be authenticated
curl --cookie "access_token=correct horse battery staple" https://127.0.0.1:3000/authenticated
#> Successfully authenticated!

# /auth2 needs to be authenticated too
curl --cookie "access_token=correct horse battery staple" https://127.0.0.1:3000/auth2
#> Successfully authenticated 2!

在处理程序中指定中间件

package main

import (
"crypto/sha256"
"crypto/subtle"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/keyauth"
)

const (
apiKey = "my-super-secret-key"
)

func main() {
app := fiber.New()

authMiddleware := keyauth.New(keyauth.Config{
Validator: func(c *fiber.Ctx, key string) (bool, error) {
hashedAPIKey := sha256.Sum256([]byte(apiKey))
hashedKey := sha256.Sum256([]byte(key))

if subtle.ConstantTimeCompare(hashedAPIKey[:], hashedKey[:]) == 1 {
return true, nil
}
return false, keyauth.ErrMissingOrMalformedAPIKey
},
})

app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Welcome")
})

app.Get("/allowed", authMiddleware, func(c *fiber.Ctx) error {
return c.SendString("Successfully authenticated!")
})

app.Listen(":3000")
}

这将导致

# / does not need to be authenticated
curl https://127.0.0.1:3000
#> Welcome

# /allowed needs to be authenticated too
curl --header "Authorization: Bearer my-super-secret-key" https://127.0.0.1:3000/allowed
#> Successfully authenticated!

配置

属性类型说明默认值
下一个func(*fiber.Ctx) boolNext 定义了一个函数,当返回 true 时跳过此中间件。nil
SuccessHandlerfiber.HandlerSuccessHandler 定义了一个函数,该函数针对有效的密钥执行。nil
ErrorHandlerfiber.ErrorHandlerErrorHandler 定义了一个函数,该函数针对无效的密钥执行。401 无效或过期的密钥
KeyLookupstringKeyLookup 是一个字符串,格式为 "<source>:<name>",用于从请求中提取密钥。"header:Authorization"
AuthSchemestringAuthScheme 用于授权标头。"Bearer"
Validatorfunc(*fiber.Ctx, string) (bool, error)Validator 是一个函数,用于验证密钥。密钥验证函数
ContextKeyinterface{}上下文键,用于将令牌中的承载令牌存储到上下文中。"token"

默认配置

var ConfigDefault = Config{
SuccessHandler: func(c *fiber.Ctx) error {
return c.Next()
},
ErrorHandler: func(c *fiber.Ctx, err error) error {
if err == ErrMissingOrMalformedAPIKey {
return c.Status(fiber.StatusUnauthorized).SendString(err.Error())
}
return c.Status(fiber.StatusUnauthorized).SendString("Invalid or expired API Key")
},
KeyLookup: "header:" + fiber.HeaderAuthorization,
AuthScheme: "Bearer",
ContextKey: "token",
}