package middleware import ( "context" "net/http" "strings" "tydata-server/app/main/api/internal/config" "tydata-server/app/main/model" jwtx "tydata-server/common/jwt" "tydata-server/common/xerr" "github.com/pkg/errors" "github.com/zeromicro/go-zero/rest/httpx" ) const ( // 定义错误码 AdminErrCodeUnauthorized = 401 ) type AdminAuthInterceptorMiddleware struct { Config config.Config // 注入model依赖 AdminUserModel model.AdminUserModel AdminUserRoleModel model.AdminUserRoleModel AdminRoleModel model.AdminRoleModel AdminApiModel model.AdminApiModel AdminRoleApiModel model.AdminRoleApiModel } func NewAdminAuthInterceptorMiddleware(c config.Config, adminUserModel model.AdminUserModel, adminUserRoleModel model.AdminUserRoleModel, adminRoleModel model.AdminRoleModel, adminApiModel model.AdminApiModel, adminRoleApiModel model.AdminRoleApiModel) *AdminAuthInterceptorMiddleware { return &AdminAuthInterceptorMiddleware{ Config: c, AdminUserModel: adminUserModel, AdminUserRoleModel: adminUserRoleModel, AdminRoleModel: adminRoleModel, AdminApiModel: adminApiModel, AdminRoleApiModel: adminRoleApiModel, } } func (m *AdminAuthInterceptorMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { // 1. JWT 校验 claims, err := m.validateJWT(r) if err != nil { httpx.Error(w, err) return } // 2. 检查用户类型是否为管理员 if claims.UserType != model.UserTypeAdmin { httpx.Error(w, errors.Wrapf(xerr.NewErrCode(xerr.TOKEN_EXPIRE_ERROR), "用户类型错误,需要管理员权限")) return } // 3. 检查平台标识 if claims.Platform != model.PlatformAdmin { httpx.Error(w, errors.Wrapf(xerr.NewErrCode(xerr.TOKEN_EXPIRE_ERROR), "平台标识错误,需要管理员平台")) return } // 4. 将用户信息放入上下文 ctx := context.WithValue(r.Context(), jwtx.ExtraKey, claims) r = r.WithContext(ctx) // 5. API 权限校验 if err := m.validateApiPermission(r.Context(), claims.UserId, r.Method, r.URL.Path); err != nil { httpx.Error(w, err) return } // 6. 通过所有校验,继续处理请求 next(w, r) } } // validateJWT 验证JWT token func (m *AdminAuthInterceptorMiddleware) validateJWT(r *http.Request) (*jwtx.JwtClaims, error) { // 从请求头中获取Authorization字段 authHeader := r.Header.Get("Authorization") if authHeader == "" { return nil, errors.Wrapf(xerr.NewErrCode(AdminErrCodeUnauthorized), "缺少Authorization头") } // 去掉Bearer前缀 token := strings.TrimPrefix(authHeader, "Bearer ") if token == authHeader { return nil, errors.Wrapf(xerr.NewErrCode(AdminErrCodeUnauthorized), "Authorization头格式错误,缺少Bearer前缀") } claims, err := jwtx.ParseJwtToken(token, m.Config.AdminConfig.AccessSecret) if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(AdminErrCodeUnauthorized), "token解析失败: %v", err) } return claims, nil } // validateApiPermission 验证API权限 func (m *AdminAuthInterceptorMiddleware) validateApiPermission(ctx context.Context, userId int64, method, path string) error { // 1. 获取用户角色 userRoles, err := m.getUserRoles(ctx, userId) if err != nil { return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取用户角色失败: %v", err) } if len(userRoles) == 0 { return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户没有分配角色") } // 2. 检查是否为超级管理员 if m.isSuperAdmin(ctx, userRoles) { // 超级管理员拥有所有权限,直接放行 return nil } // 3. 获取当前请求的API信息 api, err := m.getApiByMethodAndPath(ctx, method, path) if err != nil { // 如果API不存在,可能是公开接口,放行 return nil } // 4. 检查用户角色是否有该API权限 hasPermission, err := m.checkRoleApiPermission(ctx, userRoles, api.Id) if err != nil { return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "检查API权限失败: %v", err) } if !hasPermission { return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "权限不足,无法访问该接口") } return nil } // getUserRoles 获取用户角色 func (m *AdminAuthInterceptorMiddleware) getUserRoles(ctx context.Context, userId int64) ([]int64, error) { builder := m.AdminUserRoleModel.SelectBuilder().Where("user_id = ?", userId) userRoles, err := m.AdminUserRoleModel.FindAll(ctx, builder, "") if err != nil { return nil, err } var roleIds []int64 for _, userRole := range userRoles { roleIds = append(roleIds, userRole.RoleId) } return roleIds, nil } // isSuperAdmin 检查是否为超级管理员 func (m *AdminAuthInterceptorMiddleware) isSuperAdmin(ctx context.Context, roleIds []int64) bool { // 检查是否有超级管理员角色 for _, roleId := range roleIds { role, err := m.AdminRoleModel.FindOne(ctx, roleId) if err != nil { continue } // 检查是否为超级管理员角色 if role.RoleCode == model.AdminRoleCodeSuper { return true } } return false } // getApiByMethodAndPath 根据方法和路径获取API信息 func (m *AdminAuthInterceptorMiddleware) getApiByMethodAndPath(ctx context.Context, method, path string) (*model.AdminApi, error) { builder := m.AdminApiModel.SelectBuilder(). Where("method = ? AND url = ? AND status = ?", method, path, 1) apis, err := m.AdminApiModel.FindAll(ctx, builder, "") if err != nil { return nil, err } if len(apis) == 0 { return nil, errors.New("API不存在") } return apis[0], nil } // checkRoleApiPermission 检查角色是否有API权限 func (m *AdminAuthInterceptorMiddleware) checkRoleApiPermission(ctx context.Context, roleIds []int64, apiId int64) (bool, error) { for _, roleId := range roleIds { // 检查角色是否有该API权限 _, err := m.AdminRoleApiModel.FindOneByRoleIdApiId(ctx, roleId, apiId) if err == nil { // 找到权限记录,说明有权限 return true, nil } // 如果错误不是NotFound,说明是其他错误 if !errors.Is(err, model.ErrNotFound) { return false, err } } return false, nil }