Go Fiber权限中间件判断超级用户时出现路由无法匹配问题
问题分析与修复:Fiber中间件权限逻辑导致接口无法访问
问题现象
调用/api/users/1接口时返回Cannot GET /api/users/1,但移除HasPermissionMiddleware中的if !user.IsSuperuser {}代码块后,接口可正常响应。
原代码问题点
1. 中间件嵌套调用逻辑错误
在HasPermissionMiddleware内手动调用AuthMiddleware()(c)的方式存在冲突:
if authError := AuthMiddleware()(c); authError != nil { return authError }
常规Fiber中间件验证通过后会调用c.Next()传递请求,若在另一个中间件内手动执行该逻辑,会导致请求提前进入后续控制器流程,与当前中间件的权限校验逻辑产生冲突,最终引发响应混乱,出现路由未匹配的错误提示。
2. 超级用户权限逻辑完全写反
原代码逻辑为非超级用户直接放行,超级用户必须校验权限,这与常规的「超级用户跳过权限校验」逻辑相悖,容易导致权限控制逻辑混乱。
修复方案
步骤1:调整中间件使用方式
将AuthMiddleware作为路由组的全局中间件,而非在HasPermissionMiddleware内手动调用:
func UserManagementRoutes(app *fiber.App) { // 路由组统一添加登录验证中间件 router := app.Group("api/users", middlewares.AuthMiddleware()) router.Get("/", controllers.GetUsersListHandler) router.Get("/permissions/:id", middlewares.HasPermissionMiddleware("permissions_view"), controllers.AllPermissionOfUserHandler) // 补充用户详情接口路由(示例) router.Get("/:id", middlewares.HasPermissionMiddleware("user_view"), controllers.GetUserDetailHandler) }
步骤2:修正权限中间件逻辑
调整超级用户判断逻辑,让超级用户直接跳过权限校验,仅对非超级用户做权限检查:
func HasPermissionMiddleware(expectedPermissions ...string) fiber.Handler { return func(c *fiber.Ctx) error { user := c.Locals("user").(models.Users) // 强制要求修改初始密码 if !user.HasChangedInitPassword { return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"message": "Please change the initial password first"}) } // 超级用户直接放行 if user.IsSuperuser { return c.Next() } // 非超级用户校验权限 if !HasPermissions(expectedPermissions, user.Permissions) { joined := strings.Join(expectedPermissions, ", ") log.Printf("Requires %s access", joined) // 修正拼写错误:Insufficiant → Insufficient return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"message": "Insufficient permission access"}) } return c.Next() } }
步骤3:检查HasPermissions函数逻辑
确保函数能正确判断用户权限集合是否包含所需权限,示例逻辑参考:
// 示例:判断用户是否拥有所有所需权限 func HasPermissions(expected []string, userPermissions []string) bool { permissionMap := make(map[string]bool) for _, p := range userPermissions { permissionMap[p] = true } for _, p := range expected { if !permissionMap[p] { return false } } return true }
内容的提问来源于stack exchange,提问作者Fahad Md Kamal
相关产品推荐
相关产品推荐

