You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GoFiber同基础路由分组配置不同中间件遇权限拦截问题求助

GoFiber同基础路由组的中间件冲突解决方案

问题场景

在GoFiber框架中,为共享基础路由/的两个路由组配置不同中间件:

  • 公开路由组:无需认证,包含/、/register、/login等接口
  • 认证路由组:需启用AuthRequired中间件,包含/auth/me等接口

但访问公开路由/时,触发了认证中间件并返回401错误(提示认证头缺失),希望保留原基础路由配置,解决该冲突。

原路由代码

func GetRouter() *fiber.App {
    app := fiber.New()

    public_group := app.Group("/")
    public_group.Get("/", func(c *fiber.Ctx) error {
        return c.SendString("Hello, World 👋!")
    })

    public_group.Post("/register", handlers.RegisterUser)
    public_group.Post("/login", handlers.AuthenticateUser)
    // ...

    auth_group := app.Group("/", middleware.AuthRequired)
    auth_group.Get("/auth/me", handlers.GetUser)
    auth_group.Put("/auth/me", handlers.UpdateUser)
    auth_group.Post("/auth/me/password", handlers.UpdatePassword)
    // ...
}

服务器错误日志

auth middleware engaged
[ 2023-12-18 16:22:41 ] GET /v0 | 127.0.0.1 - ✗ Authorization header does not exist
Response: 200 [took 337.709µs]
{
  "message": "authorization header required to access this endpoint",
  "status": 401
}

AuthRequired中间件代码

package middleware

import (
    responses "backend/models/api/responses"
    "backend/utils"
    "fmt"

    fiber "github.com/gofiber/fiber/v2"
)

func AuthRequired(c *fiber.Ctx) error {
    fmt.Println("auth middleware engaged")
    auth_header := c.Get("Authorization")
    if auth_header == "" {
        return c.JSON(responses.BaseResponse{
            Status:  401,
            Message: "authorization header required to access this endpoint",
        })
    }
    if _, err := utils.ValidateJWT(auth_header); err != nil {
        return c.JSON(responses.BaseResponse{
            Status:  401,
            Message: "invalid authorization header",
        })
    }
    return c.Next()
}

问题原因

GoFiber的路由组中间件采用前缀匹配规则,当创建auth_group := app.Group("/", middleware.AuthRequired)时,该中间件会作用于所有以/为前缀的请求(即所有请求),包括公开路由的/、/register等。即使公开路由先注册,请求进来时仍会触发认证组的中间件,导致公开路由被错误拦截。

解决方案

以下两种方案无需修改原有路由路径,即可解决冲突:

方案1:给认证路由单独绑定中间件

放弃使用带中间件的根路由组,直接为每个认证接口单独添加AuthRequired中间件,确保中间件仅作用于指定认证路由,不影响公开路由:

func GetRouter() *fiber.App {
    app := fiber.New()

    public_group := app.Group("/")
    public_group.Get("/", func(c *fiber.Ctx) error {
        return c.SendString("Hello, World 👋!")
    })
    public_group.Post("/register", handlers.RegisterUser)
    public_group.Post("/login", handlers.AuthenticateUser)
    // ...

    // 直接为认证路由添加中间件,不使用根路由组
    app.Get("/auth/me", middleware.AuthRequired, handlers.GetUser)
    app.Put("/auth/me", middleware.AuthRequired, handlers.UpdateUser)
    app.Post("/auth/me/password", middleware.AuthRequired, handlers.UpdatePassword)
    // ...

    return app
}

方案2:在中间件中排除公开路由

修改AuthRequired中间件,判断当前请求路径是否属于公开路径,若是则跳过认证逻辑:

func AuthRequired(c *fiber.Ctx) error {
    // 定义所有公开路径
    publicPaths := map[string]bool{
        "/":          true,
        "/register":  true,
        "/login":     true,
        // 可添加其他公开路径
    }

    // 匹配到公开路径则直接放行
    if publicPaths[c.Path()] {
        return c.Next()
    }

    fmt.Println("auth middleware engaged")
    auth_header := c.Get("Authorization")
    if auth_header == "" {
        return c.JSON(responses.BaseResponse{
            Status:  401,
            Message: "authorization header required to access this endpoint",
        })
    }
    if _, err := utils.ValidateJWT(auth_header); err != nil {
        return c.JSON(responses.BaseResponse{
            Status:  401,
            Message: "invalid authorization header",
        })
    }
    return c.Next()
}

说明

方案1更简洁,适合认证路由数量不多的场景;方案2适合需要批量管理公开路径的场景,两种方案都能保留原有路由结构,无需修改基础路由。

内容的提问来源于stack exchange,提问作者esskayesss

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 16:43:22