This commit is contained in:
2025-11-01 13:33:20 +08:00
parent dce52f2564
commit 746e4a1b6c
2 changed files with 51 additions and 9 deletions

View File

@@ -8,6 +8,7 @@ import (
"tydata-server/app/main/api/internal/config" "tydata-server/app/main/api/internal/config"
"tydata-server/app/main/model" "tydata-server/app/main/model"
jwtx "tydata-server/common/jwt" jwtx "tydata-server/common/jwt"
"tydata-server/common/result"
"tydata-server/common/xerr" "tydata-server/common/xerr"
"github.com/pkg/errors" "github.com/pkg/errors"
@@ -50,19 +51,21 @@ func (m *AdminAuthInterceptorMiddleware) Handle(next http.HandlerFunc) http.Hand
// 1. JWT 校验 // 1. JWT 校验
claims, err := m.validateJWT(r) claims, err := m.validateJWT(r)
if err != nil { if err != nil {
httpx.Error(w, err) m.writeUnauthorizedResponse(w, err)
return return
} }
// 2. 检查用户类型是否为管理员 // 2. 检查用户类型是否为管理员
if claims.UserType != model.UserTypeAdmin { if claims.UserType != model.UserTypeAdmin {
httpx.Error(w, errors.Wrapf(xerr.NewErrCode(xerr.TOKEN_EXPIRE_ERROR), "用户类型错误,需要管理员权限")) authErr := errors.Wrapf(xerr.NewErrCode(xerr.TOKEN_EXPIRE_ERROR), "用户类型错误,需要管理员权限")
m.writeUnauthorizedResponse(w, authErr)
return return
} }
// 3. 检查平台标识 // 3. 检查平台标识
if claims.Platform != model.PlatformAdmin { if claims.Platform != model.PlatformAdmin {
httpx.Error(w, errors.Wrapf(xerr.NewErrCode(xerr.TOKEN_EXPIRE_ERROR), "平台标识错误,需要管理员平台")) authErr := errors.Wrapf(xerr.NewErrCode(xerr.TOKEN_EXPIRE_ERROR), "平台标识错误,需要管理员平台")
m.writeUnauthorizedResponse(w, authErr)
return return
} }
@@ -72,7 +75,7 @@ func (m *AdminAuthInterceptorMiddleware) Handle(next http.HandlerFunc) http.Hand
// 5. API 权限校验 // 5. API 权限校验
if err := m.validateApiPermission(r.Context(), claims.UserId, r.Method, r.URL.Path); err != nil { if err := m.validateApiPermission(r.Context(), claims.UserId, r.Method, r.URL.Path); err != nil {
httpx.Error(w, err) m.writeUnauthorizedResponse(w, err)
return return
} }
@@ -81,23 +84,45 @@ func (m *AdminAuthInterceptorMiddleware) Handle(next http.HandlerFunc) http.Hand
} }
} }
// writeUnauthorizedResponse 写入401未授权响应
func (m *AdminAuthInterceptorMiddleware) writeUnauthorizedResponse(w http.ResponseWriter, err error) {
errcode := xerr.TOKEN_EXPIRE_ERROR
errmsg := xerr.MapErrMsg(errcode)
// 从错误中提取错误码和错误消息
causeErr := errors.Cause(err)
if e, ok := causeErr.(*xerr.CodeError); ok {
errcode = e.GetErrCode()
errmsg = e.GetErrMsg()
}
// 返回401 HTTP状态码
httpx.WriteJson(w, http.StatusUnauthorized, result.Error(errcode, errmsg))
}
// validateJWT 验证JWT token // validateJWT 验证JWT token
func (m *AdminAuthInterceptorMiddleware) validateJWT(r *http.Request) (*jwtx.JwtClaims, error) { func (m *AdminAuthInterceptorMiddleware) validateJWT(r *http.Request) (*jwtx.JwtClaims, error) {
// 从请求头中获取Authorization字段 // 从请求头中获取Authorization字段
authHeader := r.Header.Get("Authorization") authHeader := r.Header.Get("Authorization")
if authHeader == "" { if authHeader == "" {
return nil, errors.Wrapf(xerr.NewErrCode(AdminErrCodeUnauthorized), "缺少Authorization头") return nil, errors.Wrapf(xerr.NewErrCode(xerr.TOKEN_EXPIRE_ERROR), "缺少Authorization头")
} }
// 去掉Bearer前缀 // 去掉Bearer前缀
token := strings.TrimPrefix(authHeader, "Bearer ") token := strings.TrimPrefix(authHeader, "Bearer ")
if token == authHeader { if token == authHeader {
return nil, errors.Wrapf(xerr.NewErrCode(AdminErrCodeUnauthorized), "Authorization头格式错误缺少Bearer前缀") return nil, errors.Wrapf(xerr.NewErrCode(xerr.TOKEN_EXPIRE_ERROR), "Authorization头格式错误缺少Bearer前缀")
} }
claims, err := jwtx.ParseJwtToken(token, m.Config.AdminConfig.AccessSecret) claims, err := jwtx.ParseJwtToken(token, m.Config.AdminConfig.AccessSecret)
if err != nil { if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(AdminErrCodeUnauthorized), "token解析失败: %v", err) // 根据错误类型返回不同的错误码
errMsg := err.Error()
if strings.Contains(errMsg, "token已过期") || strings.Contains(errMsg, "expired") {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.TOKEN_EXPIRE_ERROR), "token解析失败: %v", err)
}
// 其他JWT解析错误使用统一的token过期错误码更符合用户理解
return nil, errors.Wrapf(xerr.NewErrCode(xerr.TOKEN_EXPIRE_ERROR), "token解析失败: %v", err)
} }
return claims, nil return claims, nil

View File

@@ -66,12 +66,29 @@ func ParseJwtToken(tokenStr string, secret string) (*JwtClaims, error) {
return []byte(secret), nil return []byte(secret), nil
}) })
if err != nil || !token.Valid { if err != nil {
// 检查是否是JWT验证错误
if validationErr, ok := err.(*jwt.ValidationError); ok {
// 如果是过期错误,返回更明确的错误信息
if validationErr.Errors&jwt.ValidationErrorExpired != 0 {
return nil, errors.New("token已过期")
}
// 如果是签名错误,返回签名错误信息
if validationErr.Errors&jwt.ValidationErrorSignatureInvalid != 0 {
return nil, errors.New("token签名无效")
}
// 其他验证错误
return nil, errors.New("token验证失败")
}
return nil, errors.New("invalid JWT") return nil, errors.New("invalid JWT")
} }
if !token.Valid {
return nil, errors.New("token无效")
}
claims, ok := token.Claims.(jwt.MapClaims) claims, ok := token.Claims.(jwt.MapClaims)
if !ok || !token.Valid { if !ok {
return nil, errors.New("invalid JWT claims") return nil, errors.New("invalid JWT claims")
} }