Go語言中JWT的創(chuàng)建和解析操作詳解
JWT介紹
Json web token (JWT)
, 是為了在網(wǎng)絡(luò)應(yīng)用環(huán)境間傳遞聲明而執(zhí)行的一種基于JSON的開放標(biāo)準(zhǔn).該token被設(shè)計(jì)為緊湊且安全的,特別適用于分布式站點(diǎn)的單點(diǎn)登錄場景。JWT的聲明一般被用來在身份提供者和服務(wù)提供者間傳遞被認(rèn)證的用戶身份信息,以便于從資源服務(wù)器獲取資源,也可以增加一些額外的其它業(yè)務(wù)邏輯所必須的聲明信息,該token
也可直接被用于認(rèn)證,也可被加密。下面就以一個(gè)標(biāo)準(zhǔn)的jwt功能實(shí)現(xiàn)方式進(jìn)行編碼。并且這個(gè)jwt也會(huì)相對安全一點(diǎn),因?yàn)槭怯屑用苓^的。一般用戶登錄后生成的token都是需要進(jìn)行加密的,每一次訪問,服務(wù)端都會(huì)根據(jù)前端的請求做出對應(yīng)的策略,避免一定的非必要腳本攻擊。
JWT相對于Cookie和Session的優(yōu)點(diǎn)
Cookie和Session存放在哪,相對于JWT有啥區(qū)別?
Cookie是儲(chǔ)存在客戶端的,Session是儲(chǔ)存在服務(wù)端的。
Cookie:
1、客戶端請求服務(wù)器后,如果服務(wù)器需要記錄用戶狀態(tài),服務(wù)器會(huì)在響應(yīng)信息中包含一個(gè)Set-Cookie的響應(yīng)頭
2、客戶端會(huì)根據(jù)這個(gè)響應(yīng)頭存儲(chǔ)Cookie信息。再次請求服務(wù)器時(shí),客戶端會(huì)在請求信息中包含一個(gè)Cookie請求頭。
Session:
反正就是服務(wù)端生成,存儲(chǔ)在服務(wù)器的內(nèi)存中以及保存在文件或數(shù)據(jù)庫中,返回給前端儲(chǔ)存到cookie中
1、session是有過期時(shí)間的,可以設(shè)置過期時(shí)間或者服務(wù)器關(guān)閉就會(huì)消失
2、session多了服務(wù)端會(huì)有內(nèi)存壓力,這就需要負(fù)載均衡了以及不同服務(wù)器的session共享問題。
JWT:
1、 在頭部信息中聲明加密算法和常量, 然后把header使用json轉(zhuǎn)化為字符串
2、在載荷中聲明用戶信息,同時(shí)還有一些其他的內(nèi)容;再次使用json 把載荷部分進(jìn)行轉(zhuǎn)化,轉(zhuǎn)化為字符串 (但是你覺得載荷中應(yīng)不應(yīng)該放置敏感的信息,當(dāng)然不行,因?yàn)橛行лd荷中的內(nèi)容是base64進(jìn)行編碼的,并不是進(jìn)行加密的,而且JWT存儲(chǔ)在localstorage等等,能夠被獲取到)
3、 使用在header中聲明的加密算法和每個(gè)項(xiàng)目隨機(jī)生成的secret來進(jìn)行加密, 把第一步分字符串和第二部分的字符串進(jìn)行加密, 生成新的字符串。此字符串是獨(dú)一無二的。
4、解密的時(shí)候,只要客戶端帶著JWT來發(fā)起請求,服務(wù)端就直接使用secret進(jìn)行解密。
你可以這樣理解,JWT不受瀏覽器之間的令牌約束,并且其是有加密的,可以一定程度上得到保護(hù)。
第一部分為頭部(header),第二部分我們稱其為載荷(payload),第三部分是簽證(signature)。
實(shí)現(xiàn)jwt
引入jwt-go
我們需要先引入這個(gè)go-jwt
go get "github.com/dgrijalva/jwt-go"
創(chuàng)建一個(gè)jwt.go
jwt.StandardClaims 中有很多參數(shù),可以根據(jù)自己的需要進(jìn)行添加,可以查看源碼
// 設(shè)置token過期時(shí)間 const TokenExpireDuration = time.Hour * 2 var mySecret = []byte("努力學(xué)習(xí)go語言") // 這里可以根據(jù)自己的業(yè)務(wù)做出更改 type MyClaims struct { UserID int64 `json:"user_id"` UserName string `json:"user_name"` jwt.StandardClaims } // GenToken 生成JWT func GenToken(userId int64, username string) (string, error) { // 創(chuàng)建我們自己聲明的數(shù)據(jù) c := MyClaims{ userId, username, // 定義字段 jwt.StandardClaims{ IssuedAt: time.Now().Add(TokenExpireDuration).Unix(), // 過期時(shí)間 Issuer: "三杯溫開水", // 簽發(fā)人 }, } // 使用指定的簽名方法創(chuàng)建簽名對象 token := jwt.NewWithClaims(jwt.SigningMethodHS256, c) // 返回token return token.SignedString(mySecret) } // ParseToken 解析 JWT func ParseToken(tokenString string) (*MyClaims, error) { mc := new(MyClaims) // 解析token token, err := jwt.ParseWithClaims(tokenString, mc, func(token *jwt.Token) (i interface{}, err error) { return mySecret, nil }) if err != nil { return nil, err } if token.Valid { // 校驗(yàn)token return mc, nil } return nil, errors.New("invalid token") }
創(chuàng)建一個(gè)jwt的中間件
這個(gè)中間件一般會(huì)放置在需要用戶登錄情況下才可以進(jìn)行訪問的頁面或者數(shù)據(jù),比如:個(gè)人信息功能上。下面的是基于標(biāo)準(zhǔn)版的Authorization
中,并使用Bearer開頭。可以根據(jù)自己的業(yè)務(wù)需求進(jìn)行做出更改
// JWTAuthMiddleware 基于JWT的認(rèn)證中間件 func JWTAuthMiddleware() func(c *gin.Context) { return func(c *gin.Context) { // 這里根據(jù)自己的業(yè)務(wù)進(jìn)行更改 authHeader := c.Request.Header.Get("Authorization") if authHeader == "" { controller.ResponseError(c, controller.CodeNeedLogin) c.Abort() return } // 按空格分割(基于Bearer開頭的),如果不是Bearer開頭的下面代碼可以進(jìn)行省略 // ------ start ------ parts := strings.SplitN(authHeader, " ", 2) if !(len(parts) == 2 && parts[0] == "Bearer") { controller.ResponseError(c, controller.CodeInvalidToken) c.Abort() return } // ------ end ------- // parts[1]是獲取到的tokenString,我們使用之前定義好的解析JWT的函數(shù)來解析它 mc, err := jwt.ParseToken(parts[1]) if err != nil { controller.ResponseError(c, controller.CodeInvalidToken) c.Abort() return } // 將當(dāng)前請求的username信息保存到請求的上下文c上 c.Set(controller.CtxUserIdKey, mc.UserID) c.Next() // 后續(xù)的處理函數(shù)可以用過c.Get(CtxUserIdKey)來獲取當(dāng)前請求的用戶信息 } }
中間件引入到路由中
r.POST("/ping", JWTAuthMiddleware(), func(c *gin.Context) { c.String(http.StatusOK, "ok!") })
到此這篇關(guān)于Go語言中JWT的創(chuàng)建和解析操作詳解的文章就介紹到這了,更多相關(guān)Go JWT的創(chuàng)建和解析內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Go語言如何使用標(biāo)準(zhǔn)庫sort對切片進(jìn)行排序
Sort?標(biāo)準(zhǔn)庫提供了對基本數(shù)據(jù)類型的切片和自定義類型的切片進(jìn)行排序的函數(shù)。今天主要分享的內(nèi)容是使用?Go?標(biāo)準(zhǔn)庫?sort?對切片進(jìn)行排序,感興趣的可以了解一下2022-12-12golang rate令牌桶源碼分析實(shí)現(xiàn)方式
這篇文章主要介紹了golang rate令牌桶源碼分析實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07GO語言協(xié)程互斥鎖Mutex和讀寫鎖RWMutex用法實(shí)例詳解
這篇文章主要介紹了GO語言協(xié)程互斥鎖Mutex和讀寫鎖RWMutex用法詳解,需要的朋友可以參考下2022-04-04golang?run時(shí)報(bào)undefined錯(cuò)誤的解決
這篇文章主要介紹了golang?run時(shí)報(bào)undefined錯(cuò)誤的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03Golang實(shí)現(xiàn)SSH、SFTP操作小結(jié)
在日常的一些開發(fā)場景中,我們需要去和遠(yuǎn)程服務(wù)器進(jìn)行一些通信,本文主要介紹了Golang實(shí)現(xiàn)SSH、SFTP操作小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下2024-04-04Go語言實(shí)現(xiàn)互斥鎖、隨機(jī)數(shù)、time、List
這篇文章主要介紹了Go語言實(shí)現(xiàn)互斥鎖、隨機(jī)數(shù)、time、List的相關(guān)資料,需要的朋友可以參考下2018-10-10Go語言實(shí)現(xiàn)關(guān)閉http請求的方式總結(jié)
面試的時(shí)候問到如何關(guān)閉http請求,一般人脫口而出的是關(guān)閉response.body,這是錯(cuò)誤的。本文為大家整理了三個(gè)正確關(guān)閉http請求的方法,希望對大家有所幫助2023-02-02