diff --git a/auth/auth.go b/auth/auth.go index 46a4774..b1eed6f 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -13,6 +13,7 @@ import ( "strings" "github.com/veypi/vbase/cfg" + "github.com/veypi/vbase/libs/jwt" "github.com/veypi/vbase/models" "github.com/veypi/vigo" pub "github.com/veypi/vigo/contrib/auth" @@ -33,6 +34,9 @@ const ( LevelAdmin = 7 // 111 管理员 (完全控制) ) +// ctxKeyTokenParsed 标记token是否已解析(请求级别,避免重复解析) +const ctxKeyTokenParsed = "_token_parsed" + // PermFunc 权限检查函数类型 type PermFunc = pub.PermFunc @@ -44,9 +48,6 @@ var Factory = &authFactory{ apps: make(map[string]Provider), } -// VBaseProvider vbase 自身的权限 Provider 实例 -var VBaseProvider Provider - var _ pub.Provider = &vbaseProvider{} func init() { @@ -98,10 +99,39 @@ type vbaseProvider struct { // ========== Provider 接口实现 ========== func (a *vbaseProvider) UserID(x *vigo.X) string { - if uid, ok := x.Get(CtxKeyUserID).(string); ok { - return uid + // 1. 检查是否已解析过(无论成功与否,避免重复解析) + if _, parsed := x.Get(ctxKeyTokenParsed).(bool); parsed { + if uid, ok := x.Get(CtxKeyUserID).(string); ok { + return uid + } + return "" + } + + // 2. 惰性解析:从请求中提取 token + tokenStr := extractToken(x) + if tokenStr == "" { + x.Set(ctxKeyTokenParsed, true) + return "" + } + + // 3. 解析并验证 token + claims, err := jwt.ParseToken(tokenStr) + if err != nil { + x.Set(ctxKeyTokenParsed, true) + return "" + } + + // 确保是 access token + if !jwt.IsAccessToken(claims) { + x.Set(ctxKeyTokenParsed, true) + return "" } - return "" + + // 4. 设置到上下文中,供后续调用使用 + x.Set(CtxKeyUserID, claims.UserID) + x.Set(ctxKeyTokenParsed, true) + + return claims.UserID } // Grant 授予权限