yunzer_go/server/middleware/permission.go
2025-11-03 18:00:12 +08:00

189 lines
5.1 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 ""
}