Gin框架dgrijalva/jwt-go例項(JWT使用者認證)

蓝易云發表於2024-11-28

在Gin框架中實現基於JWT的使用者認證是現代Web應用中常見的需求。透過JWT(JSON Web Token),可以安全地在客戶端和伺服器之間傳遞使用者身份資訊。下面將詳細介紹如何在Gin框架中使用 dgrijalva/jwt-go 庫實現JWT認證。

1. 安裝依賴

首先,確保已經安裝了以下Go依賴包:

  • github.com/gin-gonic/gin:Gin框架,用於建立Web應用。
  • github.com/dgrijalva/jwt-go:JWT庫,用於生成和解析JWT。

使用以下命令來安裝這些依賴:

go get github.com/gin-gonic/gin
go get github.com/dgrijalva/jwt-go

2. 程式碼結構及邏輯

我們將分為幾個部分來實現這個JWT認證功能:

2.1. 匯入必要的包

首先需要匯入 ginjwt-go 包。

import (
    "github.com/gin-gonic/gin"
    "github.com/dgrijalva/jwt-go"
)

2.2. 初始化Gin路由

我們使用Gin框架建立路由並新增JWT中介軟體。在該路由中,有些路由需要驗證使用者身份(即JWT驗證),而有些路由則無需身份驗證。

func main() {
    router := gin.Default()

    // 新增JWT中介軟體
    router.Use(authMiddleware())

    // 新增需要認證的路由
    router.GET("/protected", protectedHandler)

    router.Run(":8080")
}

解釋

  • gin.Default():初始化一個Gin引擎。
  • router.Use(authMiddleware()):全域性新增JWT認證中介軟體,所有請求都會經過此中介軟體進行JWT驗證。
  • router.GET("/protected", protectedHandler):這是一個受保護的路由,只有透過JWT認證的使用者才能訪問。

2.3. 實現JWT中介軟體

JWT中介軟體的功能是從請求中獲取JWT令牌,解析並驗證它。如果令牌有效,允許請求繼續執行,否則返回錯誤。

func authMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        // 從請求頭獲取Authorization欄位中的token
        tokenString := c.GetHeader("Authorization")
        if tokenString == "" {
            c.JSON(401, gin.H{"error": "Authorization header missing"})
            c.Abort()
            return
        }

        // 解析JWT令牌
        token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
            return []byte("your-secret-key"), nil  // 驗證JWT的金鑰
        })

        // 驗證令牌有效性
        if err != nil || !token.Valid {
            c.JSON(401, gin.H{"error": "Invalid token"})
            c.Abort()
            return
        }

        // 如果驗證透過,允許請求繼續
        c.Next()
    }
}

解釋

  • c.GetHeader("Authorization"):從請求頭中獲取Authorization欄位,該欄位通常包含JWT令牌。
  • jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error)):使用金鑰 your-secret-key 解析JWT。如果令牌無效或過期,會返回錯誤。
  • 如果令牌無效,返回401錯誤並終止請求;如果令牌有效,則呼叫 c.Next() 允許請求繼續。

2.4. 實現受保護的路由處理程式

建立一個簡單的路由處理程式,用於響應經過JWT認證的請求。只有驗證透過的使用者才能訪問此路由。

func protectedHandler(c *gin.Context) {
    c.JSON(200, gin.H{"message": "Access granted"})
}

解釋

  • 該處理程式響應HTTP 200狀態碼,並返回一個簡單的JSON訊息 {"message": "Access granted"},表示使用者成功透過認證。

3. JWT簽名和金鑰

JWT令牌的安全性完全依賴於金鑰。在上面的程式碼中,我們使用了硬編碼的金鑰 "your-secret-key"。但在實際生產環境中,你應該確保金鑰的安全,避免洩露。你可以使用環境變數或其他方式來管理金鑰。

4. 完整程式碼示例

package main

import (
    "github.com/gin-gonic/gin"
    "github.com/dgrijalva/jwt-go"
)

func main() {
    router := gin.Default()

    // 新增JWT中介軟體
    router.Use(authMiddleware())

    // 新增需要認證的路由
    router.GET("/protected", protectedHandler)

    router.Run(":8080")
}

func authMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        tokenString := c.GetHeader("Authorization")
        if tokenString == "" {
            c.JSON(401, gin.H{"error": "Authorization header missing"})
            c.Abort()
            return
        }

        token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
            return []byte("your-secret-key"), nil
        })

        if err != nil || !token.Valid {
            c.JSON(401, gin.H{"error": "Invalid token"})
            c.Abort()
            return
        }

        c.Next()
    }
}

func protectedHandler(c *gin.Context) {
    c.JSON(200, gin.H{"message": "Access granted"})
}

5. 安全建議

  1. 金鑰管理:切勿在程式碼中直接寫死金鑰。應透過環境變數或其他安全儲存方式來管理金鑰。
  2. Token過期處理:JWT通常會設定過期時間。你可以在JWT生成時設定 exp(過期時間)欄位,並在解析時驗證過期狀態。
  3. HTTPS加密:確保API通訊透過HTTPS進行加密,避免中間人攻擊。

6. 總結

透過以上步驟,我們使用Gin框架和 dgrijalva/jwt-go 庫實現了一個簡單的JWT認證功能。這個流程主要包括:透過JWT中介軟體驗證請求中的令牌、在令牌驗證透過後允許訪問受保護的路由。確保金鑰的安全和令牌的有效性是實現JWT認證的關鍵。

在實際應用中,你可以根據需求進行更詳細的處理,例如支援JWT令牌的重新整理機制、不同的許可權角色控制等。

相關文章