golang gin 的管理后台多角色路由权限控制

文章目录

    使用 golang gin 实现一个前后端分离的后台管理系统,管理员分为:

    • 普通管理员
    • 超级管理员

    超级管理员可以访问一些普通管理员没有权限访问的接口,同时即便同一个接口两种管理员都能访问,但是可以操作的资源不同。如何设计路由及中间件可以实现清晰简洁的权限管理呢?

    例如,超级管理员是我的账号,而客户也能登录这个后台,即客户是普通管理员。我作为超级管理员可以看到后台所有的设备,而客户作为普通管理员只能看到自己所属的设备,且只能对自己的设备进行远程锁机,而不能对其他客户的设备进行操作。

    我实在是懒得自己想了,就问了一下 DeepSeek。DeepSeek AI 给出的方案,确实比我目前用的单一的 AuthMiddleware 内同时判断角色更合理:

    func SetupRouter() *gin.Engine {
      r := gin.Default()
      
      // 公共路由(登录/登出)
      public := r.Group("/api")
      {
        public.POST("/login", loginHandler)
      }
    
      // 管理员路由组(需要认证)
      auth := r.Group("/api/admin")
      auth.Use(AuthMiddleware()) // 认证中间件
      {
        // 所有管理员通用接口
        auth.GET("/profile", getProfile)
        auth.POST("/posts", createPost) // 普通管理员可创建
    
        // 超级管理员专属接口(嵌套中间件)
        super := auth.Group("")
        super.Use(SuperAdminMiddleware())
        {
          super.DELETE("/users/:id", deleteUser) // 仅超级管理员可删除用户
          super.GET("/stats", getSystemStats)
        }
      }
      
      return r
    }
    

    这种用法,确实没有想到

    super := auth.Group("")
    super.Use(SuperAdminMiddleware())
    {
        // ...
    }
    
    • 认证中间件(基础权限)。只校验 jwt token 的有效性。有效,则证明是可以登录管理后台的,即可以调用 /api/admin 前缀的接口。
    • 超级管理员校验中间件(角色权限)。在这里面再判断角色,判断是否是超级管理员。
    • 对于资源级别的权限,可能需要在每个需要控制的接口中,手动检查当前用户是否有权操作该资源,或者在服务层统一处理。例如,删除用户的操作:普通管理员只能删自己创建的,超级可以删任何。这时候,在删除的处理函数中,先获取当前用户的角色,如果是普通,检查目标用户是否是当前用户创建的,否则拒绝。

    角色分类

    • 普通管理员:admin
    • 超级管理员:superadmin

    或者衍生的角色分类

    • 超级管理员: admin
    • 客户账号:client

    前端的菜单控制

    • 客户能访问的:client。超级管理员自然也能访问。
    • 超级管理员:admin

    实际,可以简化为一个权限,就是 role 判断是否是超级管理员,然后,只需要标注需要检查超级管理员才能访问的菜单权限。

    关于作者 🌱

    我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式