fix
This commit is contained in:
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user