Go语言JWT身份认证完整实现指南

最近在学习Go语言的JWT身份认证实现,但在实际开发中遇到几个问题:

  1. 如何正确生成和解析JWT token?
  2. 在Go中应该如何安全地存储和传输JWT?
  3. 有没有推荐的库或最佳实践来处理token过期和刷新?
  4. 如何结合中间件实现路由的权限控制?
    希望能得到一份完整的实现指南,包括代码示例和常见问题的解决方案。
2 回复

使用Go实现JWT认证,推荐使用github.com/golang-jwt/jwt库。步骤:1.生成密钥;2.创建token(包含用户信息、过期时间);3.签名并返回给客户端;4.中间件验证token有效性。注意设置合理的过期时间,使用安全的签名算法(如HS256)。示例代码可在官方文档找到。


Go语言JWT身份认证完整实现指南

JWT(JSON Web Token)是一种用于安全传输信息的开放标准,常用于身份认证和授权。

核心概念

JWT由三部分组成:

  • Header(头部)
  • Payload(载荷)
  • Signature(签名)

实现步骤

1. 安装依赖

go get github.com/golang-jwt/jwt/v4

2. 定义JWT结构体

import "github.com/golang-jwt/jwt/v4"

type Claims struct {
    UserID   int    `json:"user_id"`
    Username string `json:"username"`
    jwt.RegisteredClaims
}

var jwtKey = []byte("your-secret-key")

3. 生成JWT Token

func GenerateToken(userID int, username string) (string, error) {
    expirationTime := time.Now().Add(24 * time.Hour)
    
    claims := &Claims{
        UserID:   userID,
        Username: username,
        RegisteredClaims: jwt.RegisteredClaims{
            ExpiresAt: jwt.NewNumericDate(expirationTime),
            IssuedAt:  jwt.NewNumericDate(time.Now()),
            Issuer:    "your-app-name",
        },
    }
    
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    return token.SignedString(jwtKey)
}

4. 验证JWT Token

func ValidateToken(tokenString string) (*Claims, error) {
    claims := &Claims{}
    
    token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
        return jwtKey, nil
    })
    
    if err != nil {
        return nil, err
    }
    
    if !token.Valid {
        return nil, fmt.Errorf("invalid token")
    }
    
    return claims, nil
}

5. HTTP中间件

func AuthMiddleware(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        tokenString := r.Header.Get("Authorization")
        if tokenString == "" {
            http.Error(w, "Authorization header required", http.StatusUnauthorized)
            return
        }
        
        // 去掉"Bearer "前缀
        if len(tokenString) > 7 && tokenString[:7] == "Bearer " {
            tokenString = tokenString[7:]
        }
        
        claims, err := ValidateToken(tokenString)
        if err != nil {
            http.Error(w, "Invalid token", http.StatusUnauthorized)
            return
        }
        
        // 将用户信息存入上下文
        ctx := context.WithValue(r.Context(), "user", claims)
        next.ServeHTTP(w, r.WithContext(ctx))
    }
}

6. 使用示例

func loginHandler(w http.ResponseWriter, r *http.Request) {
    // 验证用户凭据
    userID := 1
    username := "john"
    
    token, err := GenerateToken(userID, username)
    if err != nil {
        http.Error(w, "Failed to generate token", http.StatusInternalServerError)
        return
    }
    
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(map[string]string{
        "token": token,
    })
}

func protectedHandler(w http.ResponseWriter, r *http.Request) {
    claims, ok := r.Context().Value("user").(*Claims)
    if !ok {
        http.Error(w, "Unauthorized", http.StatusUnauthorized)
        return
    }
    
    w.Write([]byte(fmt.Sprintf("Hello %s!", claims.Username)))
}

安全建议

  1. 使用强密钥(至少32字符)
  2. 设置合理的过期时间
  3. 使用HTTPS传输
  4. 定期轮换密钥
  5. 在Payload中不要存储敏感信息

完整路由设置

func main() {
    http.HandleFunc("/login", loginHandler)
    http.HandleFunc("/protected", AuthMiddleware(protectedHandler))
    
    log.Println("Server starting on :8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

这个实现提供了完整的JWT身份认证流程,包括Token生成、验证和中间件保护。

回到顶部