首頁  >  文章  >  後端開發  >  使用 JWT 身份驗證保護您的 Go API

使用 JWT 身份驗證保護您的 Go API

Susan Sarandon
Susan Sarandon原創
2024-10-03 12:07:01839瀏覽

Securing Your Go API with JWT Authentication

好吧,讓我們說實話。安全性是一件大事,如果您正在建立 API,您不能讓任何人闖入並開始弄亂您的資料。這就是 JWT(JSON Web 令牌) 發揮作用的地方。今天,我們透過新增基於 JWT 的身份驗證來升級 Go API。

快速注意?

如果您一直在使用舊的 github.com/dgrijalva/jwt-go 軟體包,那麼是時候升級了。新標準是 github.com/golang-jwt/jwt/v4。

為什麼要切換?

  • 原作者移交了控制權,新的維護者一直忙於改進和修復安全問題。
  • 從 4.0.0 版本開始,他們添加了 Go 模組支援並改進了令牌驗證。
  • 如果您仍在使用舊軟體包,請查看他們的 MIGRATION_GUIDE.md。

現在,讓我們開始使用我們精美的新 JWT 庫!

JWT 又是什麼? ?

對 JWT 新手:

  • 它就像一個用於存取您的 API 的簽署授權單。
  • API 產生一個令牌,對其進行簽名,然後客戶端(使用者、應用程式等)在每個請求中包含該令牌。
  • 伺服器檢查令牌並說:「是的,你是合法的。」

現在您已經熟悉了,讓我們深入研究程式碼!


設定項目

我們將從上一篇文章離開的地方繼續。讓我們更新 Go 模組並安裝必要的軟體包:

  1. 新增 JWT 套件和 mux 路由器:
   go get github.com/golang-jwt/jwt/v4
   go get github.com/gorilla/mux
  1. 打開你的 main.go 文件,讓我們開始編碼!

第 1 步:產生 JWT 令牌

首先,我們將建立一個函數,在使用者登入時產生 JWT 令牌。該令牌將包含使用者名,並將使用金鑰進行簽署。

var jwtKey = []byte("my_secret_key")

type Credentials struct {
    Username string `json:"username"`
    Password string `json:"password"`
}

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

func generateToken(username string) (string, error) {
    expirationTime := time.Now().Add(5 * time.Minute)

    claims := &Claims{
        Username: username,
        RegisteredClaims: jwt.RegisteredClaims{
            ExpiresAt: jwt.NewNumericDate(expirationTime),
        },
    }

    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    tokenString, err := token.SignedString(jwtKey)
    return tokenString, err
}

此函數產生一個令牌,該令牌將在 5 分鐘後過期,並使用 HS256 演算法進行簽署。


第 2 步:建立登入端點

接下來,我們將建立一個登入端點,使用者可以在其中發送憑證。如果登入資訊檢查通過,我們將產生一個 JWT 並將其透過 cookie 發回。

func login(w http.ResponseWriter, r *http.Request) {
    var creds Credentials
    err := json.NewDecoder(r.Body).Decode(&creds)
    if err != nil {
        w.WriteHeader(http.StatusBadRequest)
        return
    }

    if creds.Username != "admin" || creds.Password != "password" {
        w.WriteHeader(http.StatusUnauthorized)
        return
    }

    token, err := generateToken(creds.Username)
    if err != nil {
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    http.SetCookie(w, &http.Cookie{
        Name:    "token",
        Value:   token,
        Expires: time.Now().Add(5 * time.Minute),
    })
}

步驟 3:JWT 驗證中介軟體

現在,我們需要一個中間件函數來驗證 JWT 令牌,然後才能允許存取受保護的路由。

func authenticate(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        c, err := r.Cookie("token")
        if err != nil {
            if err == http.ErrNoCookie {
                w.WriteHeader(http.StatusUnauthorized)
                return
            }
            w.WriteHeader(http.StatusBadRequest)
            return
        }

        tokenStr := c.Value
        claims := &Claims{}

        tkn, err := jwt.ParseWithClaims(tokenStr, claims, func(token *jwt.Token) (interface{}, error) {
            return jwtKey, nil
        })

        if err != nil || !tkn.Valid {
            w.WriteHeader(http.StatusUnauthorized)
            return
        }

        next.ServeHTTP(w, r)
    })
}

此中間件檢查請求是否具有有效的 JWT 令牌。如果不是,它會傳回未經授權的回應。


步驟 4:保護路由

現在,讓我們應用我們的身份驗證中間件來保護 /books 路由:

func main() {
    r := mux.NewRouter()

    r.HandleFunc("/login", login).Methods("POST")
    r.Handle("/books", authenticate(http.HandlerFunc(getBooks))).Methods("GET")

    fmt.Println("Server started on port :8000")
    log.Fatal(http.ListenAndServe(":8000", r))
}

測試 API

  1. 登入產生令牌:
   curl -X POST http://localhost:8000/login -d '{"username":"admin", "password":"password"}' -H "Content-Type: application/json"
  1. 存取受保護的 /books 端點:
   curl --cookie "token=<your_token>" http://localhost:8000/books

如果令牌有效,您將獲得存取權限。如果沒有,您將收到“401 Unauthorized”。


接下來是什麼?

下次,我們將把 API 連接到資料庫來管理使用者憑證和儲存資料。更多精彩敬請期待!

以上是使用 JWT 身份驗證保護您的 Go API的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn