This commit is contained in:
2026-10-25 21:00:08 +08:00
parent 30e5a6bed0
commit 039528e759
9 changed files with 534 additions and 12 deletions
+49
View File
@@ -2,20 +2,28 @@
package middleware
import (
"strings"
"github.com/gin-gonic/gin"
"portal-mini-go/internal/pkg/errors"
"portal-mini-go/internal/pkg/session"
"portal-mini-go/internal/repository/miniapp"
)
const (
appIDCtxKey = "app_id"
miniIDCtxKey = "mini_id"
userIDCtxKey = "user_id"
)
// headerAppID 是小程序在请求头中携带的微信 AppID 字段名。
const HeaderAppID = "X-App-ID"
// HeaderSessionToken 是小程序用户会话 token 的请求头字段名。
// 也兼容标准 Authorization: Bearer <token> 形式。
const HeaderSessionToken = "X-Session-Token"
// MiniAppAuth 校验请求头中的 app_id 是否对应一个已启用且未删除的被纳管小程序,
// 通过则将 app_id 与小程序的数据库主键注入 context,供后续 handler/service 使用。
// 用户身份最终由 (mini_id, open_id) 唯一确定。
@@ -58,3 +66,44 @@ func MiniID(c *gin.Context) uint64 {
}
return 0
}
// MiniUserAuth 校验小程序用户会话 token(由 Login 签发、存于 session.Store),
// 通过后将当前用户主键注入 context。必须在 MiniAppAuth 之后使用,
// 依赖其注入的 mini_id 确保会话归属到正确的小程序。
// token 来源:请求头 Authorization: Bearer <token> 或 X-Session-Token。
func MiniUserAuth(store session.Store) gin.HandlerFunc {
return func(c *gin.Context) {
token := SessionToken(c)
if token == "" {
c.Error(errors.ErrUnauthorized)
c.Abort()
return
}
userID, err := store.Get(c.Request.Context(), session.MaSessionKey(token))
if err != nil {
c.Error(errors.ErrUnauthorized)
c.Abort()
return
}
c.Set(userIDCtxKey, userID)
c.Next()
}
}
// UserID 从 gin.Context 取出当前已认证用户的主键。
func UserID(c *gin.Context) uint64 {
if v, ok := c.Get(userIDCtxKey); ok {
if id, ok := v.(uint64); ok {
return id
}
}
return 0
}
// SessionToken 从请求头提取小程序用户会话 token。
func SessionToken(c *gin.Context) string {
if h := c.GetHeader("Authorization"); strings.HasPrefix(h, "Bearer ") {
return strings.TrimSpace(strings.TrimPrefix(h, "Bearer "))
}
return c.GetHeader(HeaderSessionToken)
}