
深入了解 Gateway API 的推理擴展
在上面的代碼片段中,我們導入了必要的包,包括github.com/golang-jwt/jwt/v5
。我們使用函數創建一個新的 JWT 令牌jwt.NewWithClaims()
。我們將簽名方法指定為HS256
以及相關信息,例如用戶名和令牌過期時間。然后,我們使用密鑰對令牌進行簽名,并將生成的令牌作為字符串返回。
一旦我們有了令牌,我們就需要在授予對受保護資源的訪問權限之前驗證其真實性。讓我們創造驗證并解析 JWT 令牌的函數:
func verifyToken (tokenString string ) error {
token, err := jwt.Parse(tokenString, func (token *jwt.Token) ( interface {}, error ) {
return secretKey, nil
})
if err != nil {
return err
}
if !token.Valid {
return fmt.Errorf( "invalid token" )
}
return nil
}
在上面的代碼片段中,我們使用jwt.Parse()
函數來解析和驗證令牌。我們提供了一個回調函數來檢索用于簽署令牌的密鑰。如果令牌有效,我們將繼續處理請求;否則,我們返回一個錯誤,表明令牌無效。
為了保護受保護的路由,我們需要引入一個登錄系統,用戶可以在其中進行身份驗證并獲取 JWT 令牌。讓我們創建一個登錄端點,用戶可以在其中提供他們的用戶名和密碼:
func LoginHandler (w http.ResponseWriter, r *http.Request) {
w.Header().Set( "Content-Type" , "application/json" )
var u User
json.NewDecoder(r.Body).Decode(&u)
fmt.Printf( "用戶請求值 %v" , u)
if u.Username == "Chek" && u.Password == "123456" {
tokenString, err := CreateToken(u.Username)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
fmt.Errorf( "未找到用戶名" )
}
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, tokenString)
return
} else {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprint(w, "無效憑據" )
}
}
在上面的代碼片段中,我們定義了一個端點,該端點接受請求主體中包含和/login
的 POST 請求。我們通過檢查提供的憑據是否與預期值匹配來模擬用戶身份驗證。如果憑據有效,我們將使用該函數生成 JWT 令牌并將其作為響應返回。否則,我們返回適當的錯誤響應。username
password
createToken()
現在我們已經實現了登錄系統并獲得了 JWT 令牌,讓我們修改受保護的路由以要求有效的 JWT 令牌進行訪問:
func ProtectedHandler (w http.ResponseWriter, r *http.Request) {
w.Header().Set( "Content-Type" , "application/json" )
tokenString := r.Header.Get( "Authorization" )
if tokenString == "" {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprint(w, "Missing authorization header" )
return
}
tokenString = tokenString[ len ( "Bearer " ):]
err := verifyToken(tokenString)
if err != nil {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprint(w, "Invalid token" )
return
}
fmt.Fprint(w, "Welcome to the protected area" )
}
在上面的代碼片段中,我們檢查Authorization
請求標頭中是否存在有效的 JWT 令牌。如果令牌缺失或無效,我們將返回適當的錯誤響應。否則,我們將繼續提供受保護的資源。
以下是完整代碼
包主導
入(
“fmt”
“github.com/gorilla/mux”
“github.com/golang-jwt/jwt”
“net/http”
“encoding/json”
“time”
)
var secretKey = [] byte(“secret-key”)
func main () {
router:= mux.NewRouter()
router.HandleFunc(“/login”,login.LoginHandler)。方法(“POST”)
router.HandleFunc(“/protected”,login.ProtectedHandler)。方法(“GET”)
fmt.Println(“啟動服務器”)
err:= http.ListenAndServe(“localhost:4000”,router)
if err!= nil {
fmt.Println(“無法啟動服務器”,err)
}
}
func LoginHandler (w http.ResponseWriter,r *http.Request) {
w.Header().Set( "Content-Type" , "application/json" )
var u User
json.NewDecoder(r.Body).Decode(&u)
fmt.Printf( "用戶請求值 %v" , u)
if u.Username == "Chek" && u.Password == "123456" {
tokenString, err := CreateToken(u.Username)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
fmt.Errorf( "未找到用戶名" )
}
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, tokenString)
return
} else {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprint(w, "無效憑據" )
}
}
func ProtectedHandler (w http.ResponseWriter, r *http.Request) {
w.Header().Set( "Content-Type" , "application/json" )
tokenString := r.Header.Get( "Authorization" )
如果tokenString == "" {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprint(w,“缺少授權標頭”)
返回
}
tokenString = tokenString [ len(“Bearer”:]
err:= verifyToken(tokenString)
如果err!= nil{
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprint(w, "無效的令牌" )
return
}
fmt.Fprint(w, "歡迎來到保護區" )
}
func createToken (username string ) ( string , error ) {
token := jwt.NewWithClaims(jwt.SigningMethodHS256,
jwt.MapClaims{
"username" : username,
"exp" : time.Now().Add(time.Hour * 24 ).Unix(),
})
tokenString, err := token.SignedString(secretKey)
if err != nil {
return "" , err
}
return tokenString, nil
}
func verifyToken (tokenString string ) error {
token, err := jwt.Parse(tokenString, func (token *jwt.Token) ( interface {},錯誤) {
返回secretKey,nil
})
如果err != nil {
返回err
}
如果!token.Valid {
返回fmt.Errorf(“無效令牌”)
}
返回 nil
}
請注意,我們還使用 創建了一個新的 HTTP 路由器。然后,我們使用定義了和端點的http.NewRouter()
路由處理程序。最后,我們通過調用 啟動了服務器。/login
/protected
router.HandleFunc()
http.ListenAndServe(":4000", router)
此設置允許/login
端點處理登錄過程并生成 JWT 令牌,而/protected
端點在授予對受保護區域的訪問權限之前驗證 JWT 令牌。
我們可以使用Postman測試我們的應用程序,通過向登錄端點發送 Post 請求http://localhost:4000/login
,并使用我們的用戶名和密碼作為請求正文。
發布請求
響應主體返回一個 JWT 令牌eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2OTA4NzA2MjksInVzZXJuYW1lIjoiQ2hlayJ9.oPHtaTaIKwSuetkYpVwLMkKnCI-c9aGEKS5vFDBFl2Y。
我們現在發送一個 GET 請求,并在授權標頭中設置上述 JWT 令牌,以http://localhost:4000/protected
訪問受保護區域。
在本文中,我們探討了如何在 Golang 中實現 JWT 令牌身份驗證。我們學習了如何創建和簽署 JWT 令牌、驗證其真實性以及構建登錄系統以保護受保護的路由。通過將 JWT 令牌身份驗證集成到您的 Go 應用程序中,您可以增強安全性并實現無狀態身份驗證機制。