package jwt import ( "errors" "fmt" "net/http" "strings" "time" "go_blog/models" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" ) // 定义 JWT 密钥(从配置文件读取) // var jwtSecret = []byte(config.GetJWTSecret()) var jwtSecret = []byte("your-hardcoded-secret-key") // CustomClaims 自定义 JWT 载荷(包含用户 ID) type CustomClaims struct { UserID uint `json:"user_id"` jwt.RegisteredClaims } // GenerateToken 生成 JWT 令牌 func GenerateToken(user *models.Account) (string, error) { expiresAt := jwt.NewNumericDate(time.Now().Add(24 * time.Hour)) // 令牌有效期 24 小时 claims := CustomClaims{ UserID: uint(user.ID), RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: expiresAt, Issuer: "go_blog", }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString(jwtSecret) } // VerifyToken 验证 JWT 令牌并返回用户信息 func VerifyToken(tokenStr string) (*models.Account, error) { // 修改返回类型为 *models.Account token, err := jwt.ParseWithClaims(tokenStr, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) } return jwtSecret, nil }) if err != nil { return nil, err } if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid { return models.GetAccountByID(claims.UserID) // 假设 models 包新增 GetAccountByID 方法 } return nil, errors.New("invalid token") } // AuthRequired Gin 中间件:验证 JWT 令牌 func AuthRequired() gin.HandlerFunc { return func(c *gin.Context) { // 从请求头获取 Authorization 字段(格式:Bearer ) authHeader := c.GetHeader("Authorization") if authHeader == "" { c.JSON(http.StatusUnauthorized, gin.H{"error": "请提供认证令牌"}) c.Abort() return } // 解析令牌 parts := strings.SplitN(authHeader, " ", 2) if len(parts) != 2 || parts[0] != "Bearer" { c.JSON(http.StatusUnauthorized, gin.H{"error": "令牌格式错误(应为 Bearer )"}) c.Abort() return } // 验证令牌并获取用户 user, err := VerifyToken(parts[1]) if err != nil { c.JSON(http.StatusUnauthorized, gin.H{"error": "无效或过期的令牌: " + err.Error()}) c.Abort() return } // 将用户信息存入上下文(后续路由可通过 c.Get("user") 获取) c.Set("user", user) c.Next() } }