package middleware import ( "server/models" "strings" "github.com/beego/beego/v2/server/web/context" ) // PermissionMiddleware 权限验证中间件 // 根据路由的权限标识检查用户是否有访问权限 func PermissionMiddleware() func(ctx *context.Context) { return func(ctx *context.Context) { // 获取当前请求的路径 path := ctx.Input.URL() // 不需要权限验证的路径列表 publicPaths := []string{ "/api/login", "/api/logout", "/api/reset-password", "/api/program-categories/public", "/api/program-infos/public", "/api/files/public", } // 检查是否为公开路径 for _, p := range publicPaths { if path == p { return } } // 检查是否为公开预览接口 if strings.HasPrefix(path, "/api/files/public-preview/") { return } // 获取用户ID userIdData := ctx.Input.GetData("userId") if userIdData == nil { // 如果没有用户ID,说明未登录,这个应该在JWT中间件中处理 // 这里直接返回,因为JWT中间件已经拦截了 return } userId, ok := userIdData.(int) if !ok { ctx.Output.JSON(map[string]interface{}{ "success": false, "message": "用户ID格式错误", }, false, false) return } // 获取当前路由对应的权限标识 permission := getPermissionByPath(path, ctx.Input.Method()) // 如果没有权限标识,说明该接口不需要权限控制 if permission == "" { return } // 检查用户是否拥有该权限 hasPermission, err := models.CheckUserPermission(userId, permission) if err != nil { ctx.Output.JSON(map[string]interface{}{ "success": false, "message": "权限验证失败", "error": err.Error(), }, false, false) return } if !hasPermission { ctx.Output.JSON(map[string]interface{}{ "success": false, "message": "您没有权限访问此接口", "code": 403, }, false, false) return } } } // getPermissionByPath 根据路径和方法获取权限标识 // 这是一个简化版本,实际应该从数据库中动态获取路由-权限映射关系 func getPermissionByPath(path, method string) string { // 权限映射表(路径模式 -> 权限标识) // 这里只列举了部分示例,实际应该从数据库中加载 permissionMap := map[string]string{ // 用户管理 "GET:/api/allUsers": "user:list", "GET:/api/user/:id": "user:detail", "POST:/api/addUser": "user:add", "POST:/api/editUser/:id": "user:edit", "DELETE:/api/deleteUser/:id": "user:delete", "POST:/api/changePassword/:id":"user:changePassword", // 角色管理 "GET:/api/roles": "role:list", "POST:/api/roles": "role:create", "GET:/api/roles/:id": "role:detail", "POST:/api/roles/:id": "role:update", "DELETE:/api/roles/:id": "role:delete", // 菜单管理 "GET:/api/allmenu": "menu:list", "POST:/api/menu": "menu:create", "PUT:/api/menu/:id": "menu:update", "DELETE:/api/menu/:id": "menu:delete", // 文件管理 "GET:/api/files": "file:list", "POST:/api/files": "file:upload", "GET:/api/files/my": "file:my", "GET:/api/files/download/:id": "file:download", "GET:/api/files/preview/:id": "file:preview", "GET:/api/files/:id": "file:detail", "PUT:/api/files/:id": "file:update", "DELETE:/api/files/:id": "file:delete", "GET:/api/files/search": "file:search", "GET:/api/files/statistics": "file:statistics", // 租户管理 "GET:/api/tenant/list": "tenant:list", "POST:/api/tenant": "tenant:create", "PUT:/api/tenant/:id": "tenant:update", "DELETE:/api/tenant/:id": "tenant:delete", "POST:/api/tenant/:id/audit": "tenant:audit", "GET:/api/tenant/:id": "tenant:detail", // 知识库 "GET:/api/knowledge/list": "knowledge:list", "GET:/api/knowledge/detail": "knowledge:detail", "POST:/api/knowledge/create": "knowledge:create", "POST:/api/knowledge/update": "knowledge:update", "POST:/api/knowledge/delete": "knowledge:delete", } // 匹配路径(简化版本,不支持动态参数匹配) key := method + ":" + path if perm, ok := permissionMap[key]; ok { return perm } // 尝试匹配动态路由(简单的ID参数替换) // 例如:/api/user/123 -> /api/user/:id pathParts := strings.Split(path, "/") for pattern, perm := range permissionMap { parts := strings.Split(pattern, ":") if len(parts) != 2 { continue } methodPart := parts[0] pathPattern := parts[1] if methodPart != method { continue } patternParts := strings.Split(pathPattern, "/") if len(patternParts) != len(pathParts) { continue } match := true for i, part := range patternParts { if strings.HasPrefix(part, ":") { // 动态参数,跳过 continue } if part != pathParts[i] { match = false break } } if match { return perm } } // 如果没有找到匹配的权限标识,返回空字符串(表示不需要权限控制) return "" }