189 lines
5.3 KiB
Go
189 lines
5.3 KiB
Go
package middleware
|
|
|
|
import (
|
|
"server/services"
|
|
"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 := services.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 ""
|
|
}
|
|
|