golang jwt鑒權(quán)的實(shí)現(xiàn)流程
JWT(JSON Web Token)是一種用于在網(wǎng)絡(luò)應(yīng)用環(huán)境間傳遞聲明(Claims)的無(wú)狀態(tài)、獨(dú)立、緊湊和獨(dú)立的信息格式。以下是 JWT 進(jìn)行鑒權(quán)的基本流程:
1. 用戶登錄
用戶通過(guò)用戶名和密碼登錄系統(tǒng),系統(tǒng)驗(yàn)證用戶身份。
2. 生成 JWT 令牌
系統(tǒng)驗(yàn)證用戶身份成功后,生成一個(gè) JWT 令牌。JWT 令牌通常包含以下部分:
Header(頭部):包含令牌的類型(通常是 JWT)和使用的簽名算法(如 HMAC-SHA256)。
Payload(載荷):包含聲明(Claims),這些聲明可以是用戶 ID、角色、過(guò)期時(shí)間等。
Signature(簽名):用于驗(yàn)證 JWT 的完整性和真實(shí)性。
3. 返回 JWT 令牌
系統(tǒng)將生成的 JWT 令牌返回給客戶端(通常是瀏覽器或移動(dòng)應(yīng)用)。
4. 客戶端存儲(chǔ) JWT 令牌
客戶端收到 JWT 令牌后,通常會(huì)將其存儲(chǔ)在本地存儲(chǔ)(如 localStorage
或 sessionStorage
)或 Cookie 中。
5. 客戶端發(fā)送請(qǐng)求
客戶端在后續(xù)的請(qǐng)求中,將 JWT 令牌放在 HTTP 請(qǐng)求頭的 Authorization
字段中,格式通常為 Bearer <token>
。
6. 服務(wù)端驗(yàn)證 JWT 令牌
服務(wù)端接收到請(qǐng)求后,從 Authorization
請(qǐng)求頭中提取 JWT 令牌,并進(jìn)行驗(yàn)證:
驗(yàn)證簽名:使用與生成 JWT 時(shí)相同的密鑰驗(yàn)證 JWT 的簽名是否有效。
驗(yàn)證過(guò)期時(shí)間:檢查 JWT 的過(guò)期時(shí)間是否已過(guò)。
驗(yàn)證其他聲明:根據(jù)需要驗(yàn)證其他聲明,如用戶角色、權(quán)限等。
7. 處理請(qǐng)求
如果 JWT 令牌驗(yàn)證通過(guò),服務(wù)端處理請(qǐng)求并返回響應(yīng)。如果驗(yàn)證失敗,返回錯(cuò)誤響應(yīng)(如 401 Unauthorized)。
示例代碼
生成 JWT 令牌(服務(wù)端)
package main import ( "fmt" "time" "github.com/golang-jwt/jwt" ) // 自定義 Claims type CustomClaims struct { UserID string `json:"user_id"` Role string `json:"role"` jwt.StandardClaims } func main() { // 自定義 Claims claims := CustomClaims{ UserID: "12345", Role: "admin", StandardClaims: jwt.StandardClaims{ ExpiresAt: time.Now().Add(24 * time.Hour).Unix(), Issuer: "myapp", }, } // 密鑰 jwtSecret := "mysecretkey" // 創(chuàng)建 JWT 令牌 token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) // 使用密鑰簽名并生成字符串形式的 JWT 令牌 tokenString, err := token.SignedString([]byte(jwtSecret)) if err != nil { fmt.Println("生成令牌失敗:", err) return } fmt.Println("生成的 JWT 令牌:", tokenString) }
驗(yàn)證 JWT 令牌(服務(wù)端)
package main import ( "fmt" "net/http" "strings" "github.com/golang-jwt/jwt" ) // 自定義 Claims type CustomClaims struct { UserID string `json:"user_id"` Role string `json:"role"` jwt.StandardClaims } func handler(w http.ResponseWriter, r *http.Request) { // 獲取 Authorization 請(qǐng)求頭 authHeader := r.Header.Get("Authorization") // 檢查 Authorization 請(qǐng)求頭是否存在 if authHeader == "" { http.Error(w, "Missing Authorization header", http.StatusUnauthorized) return } // 提取 JWT 令牌 tokenString := strings.TrimPrefix(authHeader, "Bearer ") // 驗(yàn)證 JWT 令牌 token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) { // 提供簽名密鑰 return []byte("mysecretkey"), nil }) if err != nil { http.Error(w, "Invalid token", http.StatusUnauthorized) return } if !token.Valid { http.Error(w, "Invalid token", http.StatusUnauthorized) return } // 處理請(qǐng)求 fmt.Fprintf(w, "Hello, World!") } func main() { http.HandleFunc("/api/data", handler) http.ListenAndServe(":8080", nil) }
可以將驗(yàn)證jwt令牌的方法定義為中間件(Middleware),通過(guò)Use方法注冊(cè)到gin中,應(yīng)用于所有路由。gin的中間件在請(qǐng)求處理流程中被調(diào)用,可以對(duì)請(qǐng)求進(jìn)行預(yù)處理、修改請(qǐng)求或響應(yīng),甚至可以終止請(qǐng)求的處理。中間件在 Gin 中非常常用,可以用于實(shí)現(xiàn)諸如身份驗(yàn)證、日志記錄、請(qǐng)求限制等功能。
示例代碼:
package main import ( "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt" "strings" ) // 自定義 Claims type CustomClaims struct { UserID string `json:"user_id"` Role string `json:"role"` jwt.StandardClaims } // Auth 返回一個(gè) Gin 中間件函數(shù) func Auth() gin.HandlerFunc { return func(c *gin.Context) { // 獲取 Authorization 請(qǐng)求頭 authHeader := c.GetHeader("Authorization") // 檢查 Authorization 請(qǐng)求頭是否存在 if authHeader == "" { c.JSON(401, gin.H{"error": "Missing Authorization header"}) c.Abort() return } // 提取 JWT 令牌 tokenString := strings.TrimPrefix(authHeader, "Bearer ") // 驗(yàn)證 JWT 令牌 token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) { // 提供簽名密鑰 return []byte("mysecretkey"), nil }) if err != nil { c.JSON(401, gin.H{"error": "Invalid token"}) c.Abort() return } if !token.Valid { c.JSON(401, gin.H{"error": "Invalid token"}) c.Abort() return } // 如果驗(yàn)證通過(guò),繼續(xù)處理請(qǐng)求 c.Next() } } func main() { r := gin.Default() // 使用 Auth 中間件 r.Use(Auth()) r.GET("/api/data", func(c *gin.Context) { c.JSON(200, gin.H{"message": "Hello, World!"}) }) r.Run(":8080") }
到此這篇關(guān)于golang jwt鑒權(quán)的實(shí)現(xiàn)流程的文章就介紹到這了,更多相關(guān)golang jwt鑒權(quán)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go語(yǔ)言中的流程控制結(jié)構(gòu)和函數(shù)詳解
這篇文章主要介紹了Go語(yǔ)言中的流程控制結(jié)構(gòu)和函數(shù)詳解,本文詳細(xì)講解了if、goto、for、switch等控制語(yǔ)句,同時(shí)對(duì)函數(shù)相關(guān)知識(shí)做了講解,需要的朋友可以參考下2014-10-10golang使用http client發(fā)起get和post請(qǐng)求示例
這篇文章主要介紹了golang使用http client發(fā)起get和post請(qǐng)求示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02go語(yǔ)言單例模式(Singleton)實(shí)例分析
這篇文章主要介紹了go語(yǔ)言單例模式(Singleton),實(shí)例分析了單例模式的原理與Go語(yǔ)言的實(shí)現(xiàn)技巧,需要的朋友可以參考下2015-03-03Golang詳細(xì)講解常用Http庫(kù)及Gin框架的應(yīng)用
下面這篇文章主要給大家介紹了關(guān)于Golang常用的Http庫(kù)及Gin框架,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06解決vscode中g(shù)olang插件依賴安裝失敗問(wèn)題
這篇文章主要介紹了解決vscode中g(shù)olang插件依賴安裝失敗問(wèn)題,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-08-08Go語(yǔ)言操作Excel的實(shí)現(xiàn)示例
excelize是一個(gè)功能豐富且易于使用的Go語(yǔ)言庫(kù),它極大地簡(jiǎn)化了Excel文件的讀寫操作,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-12-12如何使用Goland IDE go mod 方式構(gòu)建項(xiàng)目
這篇文章主要介紹了如何使用Goland IDE go mod 方式構(gòu)建項(xiàng)目,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10Go語(yǔ)言基礎(chǔ)知識(shí)總結(jié)(語(yǔ)法、變量、數(shù)值類型、表達(dá)式、控制結(jié)構(gòu)等)
這篇文章主要介紹了Go語(yǔ)言基礎(chǔ)知識(shí)總結(jié)(語(yǔ)法、變量、數(shù)值類型、表達(dá)式、控制結(jié)構(gòu)等),本文匯總了Go語(yǔ)言的入門知識(shí),需要的朋友可以參考下2014-10-10