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/model"
jwtx "tydata-server/common/jwt"
"tydata-server/common/result"
"tydata-server/common/xerr"
"github.com/pkg/errors"
@@ -50,19 +51,21 @@ func (m *AdminAuthInterceptorMiddleware) Handle(next http.HandlerFunc) http.Hand
// 1. JWT 校验
claims, err := m.validateJWT(r)
if err != nil {
httpx.Error(w, err)
m.writeUnauthorizedResponse(w, err)
return
}
// 2. 检查用户类型是否为管理员
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
}
// 3. 检查平台标识
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
}
@@ -72,7 +75,7 @@ func (m *AdminAuthInterceptorMiddleware) Handle(next http.HandlerFunc) http.Hand
// 5. API 权限校验
if err := m.validateApiPermission(r.Context(), claims.UserId, r.Method, r.URL.Path); err != nil {
httpx.Error(w, err)
m.writeUnauthorizedResponse(w, err)
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
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头")
return nil, errors.Wrapf(xerr.NewErrCode(xerr.TOKEN_EXPIRE_ERROR), "缺少Authorization头")
}
// 去掉Bearer前缀
token := strings.TrimPrefix(authHeader, "Bearer ")
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)
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

View File

@@ -66,12 +66,29 @@ func ParseJwtToken(tokenStr string, secret string) (*JwtClaims, error) {
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")
}
if !token.Valid {
return nil, errors.New("token无效")
}
claims, ok := token.Claims.(jwt.MapClaims)
if !ok || !token.Valid {
if !ok {
return nil, errors.New("invalid JWT claims")
}