This commit is contained in:
2025-09-30 17:44:18 +08:00
parent 898339fd5d
commit f4b7e6e2df
393 changed files with 4530 additions and 2061 deletions

View File

@@ -0,0 +1,209 @@
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
}

View File

@@ -4,9 +4,9 @@ import (
"context"
"net/http"
"hm-server/app/main/api/internal/config"
jwtx "hm-server/common/jwt"
"hm-server/common/xerr"
"tydata-server/app/main/api/internal/config"
jwtx "tydata-server/common/jwt"
"tydata-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/rest/httpx"

View File

@@ -1,10 +1,10 @@
package middleware
import (
"tydata-server/app/main/model"
"tydata-server/common/ctxdata"
"tydata-server/common/xerr"
"net/http"
"hm-server/app/main/model"
"hm-server/common/ctxdata"
"hm-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/rest/httpx"