Gin框架如何对课程静态资源做用户权限校验,未注册课程用户返回404
Gin静态课程资源权限校验实现方案
核心思路
废弃默认无权限校验的Static静态路由,给/Content前缀的路由绑定JWT身份校验+购课权限校验两层中间件,仅校验通过的请求才返回静态资源,否则统一返回404。
实现步骤
- 第一步:移除原有的
route.Static("/Content","./Media")配置,改用自定义路由组处理静态资源请求 - 第二步:编写权限校验中间件,核心逻辑如下:
- 从请求头中读取JWT Token,校验合法性,校验失败直接返回404
- 从有效Token中解析出用户唯一HashID
- 从请求URI中提取课程唯一标识:例如请求路径为
/Content/Courses/CourseOne/Unit_1/image/1.jpg,拆分路径后获取课程ID为CourseOne - 查表
UserCourses对应用户HashID+课程ID的记录,判断isRegistered字段是否为true - 权限校验不通过直接返回404,校验通过则由后续的静态资源处理器返回对应文件
- 第三步:注册路由和中间件
代码示例
// 资源权限校验中间件 func CourseResourceAuth() gin.HandlerFunc { return func(c *gin.Context) { // 1. 校验JWT,获取用户HashID token := c.GetHeader("Authorization") hashID, err := parseJWT(token) // 调用你现有的JWT解析逻辑即可 if err != nil { c.AbortWithStatus(http.StatusNotFound) return } // 2. 从请求路径提取课程ID // 先统一转换路径分隔符,兼容Windows生成的存储路径 path := strings.ReplaceAll(c.Request.URL.Path, "\\", "/") pathSegments := strings.Split(path, "/") // 路径格式为 /Content/Courses/{courseID}/xxx,索引3的位置为课程ID,可根据你的实际路径调整索引 if len(pathSegments) < 4 { c.AbortWithStatus(http.StatusNotFound) return } courseID := pathSegments[3] // 3. 校验用户是否已购买该课程 var isRegistered bool err = db.Model(&UserCourses{}). Where("hash_id = ? AND course_id = ?", hashID, courseID). Select("isRegistered"). First(&isRegistered).Error if err != nil || !isRegistered { c.AbortWithStatus(http.StatusNotFound) return } // 校验通过,放行请求 c.Next() } } // 路由注册 func initRouter() *gin.Engine { r := gin.Default() // 其他原有路由注册逻辑... // 替换原有Static路由,先绑定校验中间件,再用StaticFS处理静态资源 contentGroup := r.Group("/Content", CourseResourceAuth()) { contentGroup.StaticFS("/", http.Dir("./Media")) } return r }
注意事项
- 如果你的课程ID所在路径层级不同,调整
pathSegments的索引值即可适配 - 所有无权限、路径非法、Token无效的场景都统一返回404,避免泄露资源存在的信息
内容的提问来源于stack exchange,提问作者Mohammad Derakhshan
相关产品推荐
相关产品推荐

