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. 用戶(hù)登錄
用戶(hù)通過(guò)用戶(hù)名和密碼登錄系統(tǒng),系統(tǒng)驗(yàn)證用戶(hù)身份。
2. 生成 JWT 令牌
系統(tǒng)驗(yàn)證用戶(hù)身份成功后,生成一個(gè) JWT 令牌。JWT 令牌通常包含以下部分:
Header(頭部):包含令牌的類(lèi)型(通常是 JWT)和使用的簽名算法(如 HMAC-SHA256)。
Payload(載荷):包含聲明(Claims),這些聲明可以是用戶(hù) ID、角色、過(guò)期時(shí)間等。
Signature(簽名):用于驗(yàn)證 JWT 的完整性和真實(shí)性。
3. 返回 JWT 令牌
系統(tǒng)將生成的 JWT 令牌返回給客戶(hù)端(通常是瀏覽器或移動(dòng)應(yīng)用)。
4. 客戶(hù)端存儲(chǔ) JWT 令牌
客戶(hù)端收到 JWT 令牌后,通常會(huì)將其存儲(chǔ)在本地存儲(chǔ)(如 localStorage 或 sessionStorage)或 Cookie 中。
5. 客戶(hù)端發(fā)送請(qǐng)求
客戶(hù)端在后續(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)證其他聲明,如用戶(hù)角色、權(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ǔ)言之?dāng)?shù)組和切片使用及說(shuō)明
Go語(yǔ)言中數(shù)組是固定大小的值類(lèi)型,切片是動(dòng)態(tài)引用類(lèi)型,包含指針、長(zhǎng)度和容量,切片支持追加、刪除等操作,但不能直接比較,數(shù)組長(zhǎng)度固定,切片可靈活擴(kuò)容,常用于動(dòng)態(tài)數(shù)據(jù)場(chǎng)景2025-09-09
Go語(yǔ)言基礎(chǔ)學(xué)習(xí)之Context的使用詳解
在Go語(yǔ)言中,Context是一個(gè)非常重要的概念,它用于在不同的?goroutine?之間傳遞請(qǐng)求域的相關(guān)數(shù)據(jù),本文將深入探討Go語(yǔ)言中?Context特性和Context的高級(jí)使用方法,希望對(duì)大家有所幫助2023-05-05
golang如何用http.NewRequest創(chuàng)建get和post請(qǐng)求
這篇文章主要介紹了golang如何用http.NewRequest創(chuàng)建get和post請(qǐng)求問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03
Golang實(shí)現(xiàn)短網(wǎng)址/短鏈服務(wù)的開(kāi)發(fā)筆記分享
這篇文章主要為大家詳細(xì)介紹了如何使用Golang實(shí)現(xiàn)短網(wǎng)址/短鏈服務(wù),文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以了解一下2023-05-05
Go 通過(guò)結(jié)構(gòu)struct實(shí)現(xiàn)接口interface的問(wèn)題
這篇文章主要介紹了Go 通過(guò)結(jié)構(gòu)struct實(shí)現(xiàn)接口interface的問(wèn)題,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-10-10
Go中Gzip與json搭配實(shí)現(xiàn)數(shù)據(jù)壓縮demo
這篇文章主要為大家介紹了Go中Gzip與json搭配使用壓縮數(shù)據(jù)的實(shí)現(xiàn)demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
Go和Java算法詳析之分?jǐn)?shù)到小數(shù)
這篇文章主要給大家介紹了關(guān)于Go和Java算法詳析之分?jǐn)?shù)到小數(shù)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-08-08
Golang中正則表達(dá)式語(yǔ)法及相關(guān)示例
正則表達(dá)式是一種用于匹配和操作文本的強(qiáng)大工具,它使用特殊的字符和語(yǔ)法來(lái)定義模式,下面這篇文章主要給大家介紹了關(guān)于Golang中正則表達(dá)式語(yǔ)法及相關(guān)示例的相關(guān)資料,需要的朋友可以參考下2024-05-05

