好吧,讓我們說實話。安全性是一件大事,如果您正在建立 API,您不能讓任何人闖入並開始弄亂您的資料。這就是 JWT(JSON Web 令牌) 發揮作用的地方。今天,我們透過新增基於 JWT 的身份驗證來升級 Go API。
如果您一直在使用舊的 github.com/dgrijalva/jwt-go 軟體包,那麼是時候升級了。新標準是 github.com/golang-jwt/jwt/v4。
為什麼要切換?
現在,讓我們開始使用我們精美的新 JWT 庫!
對 JWT 新手:
現在您已經熟悉了,讓我們深入研究程式碼!
我們將從上一篇文章離開的地方繼續。讓我們更新 Go 模組並安裝必要的軟體包:
go get github.com/golang-jwt/jwt/v4 go get github.com/gorilla/mux
首先,我們將建立一個函數,在使用者登入時產生 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 演算法進行簽署。
接下來,我們將建立一個登入端點,使用者可以在其中發送憑證。如果登入資訊檢查通過,我們將產生一個 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), }) }
現在,我們需要一個中間件函數來驗證 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 令牌。如果不是,它會傳回未經授權的回應。
現在,讓我們應用我們的身份驗證中間件來保護 /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)) }
curl -X POST http://localhost:8000/login -d '{"username":"admin", "password":"password"}' -H "Content-Type: application/json"
curl --cookie "token=<your_token>" http://localhost:8000/books
如果令牌有效,您將獲得存取權限。如果沒有,您將收到“401 Unauthorized”。
下次,我們將把 API 連接到資料庫來管理使用者憑證和儲存資料。更多精彩敬請期待!
以上是使用 JWT 身份驗證保護您的 Go API的詳細內容。更多資訊請關注PHP中文網其他相關文章!