From 5b8cbb025f178d99018fb22e614483153073ccf5 Mon Sep 17 00:00:00 2001 From: hhs <386998068@qq.com> Date: Sun, 14 Jun 2026 17:13:54 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=20JWT=20=E8=AE=A4?= =?UTF-8?q?=E8=AF=81=E4=B8=AD=E9=97=B4=E4=BB=B6=EF=BC=88AuthMiddleware?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/auth/middleware.go | 54 +++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 backend/internal/auth/middleware.go diff --git a/backend/internal/auth/middleware.go b/backend/internal/auth/middleware.go new file mode 100644 index 0000000..a932240 --- /dev/null +++ b/backend/internal/auth/middleware.go @@ -0,0 +1,54 @@ +package auth + +import ( + "net/http" + "strings" + + "github.com/gin-gonic/gin" +) + +// contextKey 用于在 Gin context 中存储 Claims 的 key。 +const ( + ContextKeyUserID = "user_id" + ContextKeyUsername = "username" +) + +// AuthMiddleware 返回 Gin 中间件,从 Authorization: Bearer 提取并校验 JWT。 +// 校验成功后将 user_id 和 username 写入 Gin Context。 +func AuthMiddleware(tokenMgr *TokenManager) gin.HandlerFunc { + return func(c *gin.Context) { + authHeader := c.GetHeader("Authorization") + if authHeader == "" { + c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ + "code": "INVALID_TOKEN", + "message": "missing authorization header", + }) + return + } + + // 提取 Bearer token + parts := strings.SplitN(authHeader, " ", 2) + if len(parts) != 2 || !strings.EqualFold(parts[0], "Bearer") { + c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ + "code": "INVALID_TOKEN", + "message": "invalid authorization format", + }) + return + } + + claims, err := tokenMgr.ValidateAccess(parts[1]) + if err != nil { + c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ + "code": "INVALID_TOKEN", + "message": "invalid or expired token", + }) + return + } + + // 将用户信息写入 context + c.Set(ContextKeyUserID, claims.UserID) + c.Set(ContextKeyUsername, claims.Username) + + c.Next() + } +}