您好,登錄后才能下訂單哦!
如何用Golang實(shí)現(xiàn)一套靈活的JWT庫,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。
JWT 全 chen JSON Web Tokens 現(xiàn)在被廣泛的應(yīng)用于各種前后端分離的場(chǎng)景,他比傳統(tǒng)的 Token Session 方式,更具靈活性。
當(dāng)然網(wǎng)上也有很多開源的 JWT 庫,非常之多,開源組織也提供了官方的庫。
我最近自己寫的一個(gè) JWT 庫,代碼已經(jīng)上傳到 github 上了,地址如下:
https://github.com/liu578101804/go-tool/tree/master/jwt
相比出名的 JWT 庫來說,我沒有任何優(yōu)勢(shì),只是作為學(xué)習(xí)使用,歡迎大家指正其中的不足。
下面就給大家說下我的實(shí)現(xiàn)思路吧。
JWT 的原理
我們要實(shí)現(xiàn) JWT 算法就得先了解他的原理,我盡量用剪短的話去解釋:
JWT 算法輸出的數(shù)據(jù)是一串包含 header(頭信息).payload(內(nèi)容).signature(簽名) 的一段字符串。
來一段真實(shí)的 JWT 生成的字符串:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
是不是豁然開朗了,這串字符串又叫 token ,因?yàn)檫@串 token 里面包含了驗(yàn)證需要的信息,相比傳統(tǒng)的 session 需要到服務(wù)器里面去取驗(yàn)證的信息,更加的靈活獨(dú)立。
因?yàn)樗灰蕾?session 這種傳統(tǒng)的存儲(chǔ),別用在分布式服務(wù)器里面有著很大的優(yōu)勢(shì)。
當(dāng)然他也有缺點(diǎn),最頭痛就這 2 點(diǎn):
不可控。一旦簽發(fā)出去的 token 將無法提前讓他銷毀,不像傳統(tǒng)的,我可以把我 session 里面的 token 刪了下次過來,token 就失效了。當(dāng)然這也不是沒辦法解決,在整個(gè)體系里面加入黑名單機(jī)制就行,只是稍微麻煩了點(diǎn)。
信息相對(duì)傳統(tǒng)的 session 數(shù)據(jù)量和隱私性沒那么好。因?yàn)?token 一般都不建議特別長(zhǎng),所以 payload 承載的數(shù)據(jù)量是有限的。同時(shí)字符串里面的 payload 是可以被解密的,所以存在一定性的被破譯風(fēng)險(xiǎn)(當(dāng)然你可以使用比較難破譯的算法去降低這個(gè)風(fēng)險(xiǎn))。
算法組成
JWT 的算法組成很簡(jiǎn)單,只需要 一個(gè)可逆的加密算法去加密 header(頭信息).payload(內(nèi)容),一個(gè)不可逆的算法去對(duì)前面這部分內(nèi)容進(jìn)行加密簽名生成 signature(簽名) 就行。
如果我們用不同的加密算法組合便形成了不同的 JWT 加密算法。比如:
HS256 (HMAC + SHA-256)
RS256 (RSA + SHA-256)
當(dāng)然還有很多,你可以自己去組合,我們將寫的這個(gè)庫支持你自定義。
具體實(shí)現(xiàn)
下面就開始進(jìn)入代碼實(shí)現(xiàn)階段了:
說下我的設(shè)計(jì)思路,Golang 他有一個(gè)天然的優(yōu)勢(shì)就是支持把函數(shù)作為變量傳入,我們便可以根據(jù)這一特性把加密部分讓調(diào)用者去實(shí)現(xiàn),我們把實(shí)現(xiàn)主體就行,這樣便我們的 JWT 便非常靈活了。
我們要寫的主體代碼去掉注釋空行不到 100 行。
jwt.go
package jwt import ( "encoding/json" "strings" "fmt" ) //聲明一個(gè)標(biāo)準(zhǔn)的JWT接口 type IJwt interface { //設(shè)置頭部 SetHeader(string) //設(shè)置簽名算法 SetSignFunc(SignFunc) //設(shè)置編碼算法 SetEncodeFunc(EncodeFunc) //寫入body WriteBody(map[string]interface{}) //生成jwt CreateJwtString() (string,error) //驗(yàn)證jwt CheckJwtString(string) bool } //規(guī)范header的格式 type Header struct { Type string `json:"type"` Alg string `json:"alg"` } //簽名算法 type SignFunc func([]byte) string //編碼算法 type EncodeFunc func([]byte) string //聲明一個(gè)結(jié)構(gòu)圖 去實(shí)現(xiàn) 標(biāo)準(zhǔn)的JWT接口 type Jwt struct { Header Header Body map[string]interface{} signFun SignFunc encodeFun EncodeFunc } //設(shè)置頭部信息,說明你使用的簽名算法 func (j *Jwt) SetHeader(headerType string){ j.Header = Header{ Type: "JWT", Alg: headerType, } } //設(shè)置簽名算法 func (j *Jwt) SetSignFunc(signFunc SignFunc) { j.signFun = signFunc } //設(shè)置對(duì) header 和 body 的加密算法 func (j *Jwt) SetEncodeFunc(encodeFunc EncodeFunc) { j.encodeFun = encodeFunc } //寫入要加密的內(nèi)容 func (j *Jwt) WriteBody(body map[string]interface{}) { j.Body = body } //生成token func (j *Jwt) CreateJwtString() (string,error) { //編碼header headerByte,err := json.Marshal(j.Header) if err != nil { return "",err } headerStr := j.encodeFun(headerByte) //編碼body bodyByte,err := json.Marshal(j.Body) if err != nil { return "",err } bodyStr := j.encodeFun(bodyByte) //簽名 signByte := j.signFun([]byte(string(headerStr)+"."+string(bodyStr))) return fmt.Sprintf("%s.%s.%s",headerStr,bodyStr,signByte),nil } //驗(yàn)證 token 是否合規(guī) func (j *Jwt) CheckJwtString(input string) bool { arr := strings.Split(input,".") //格式是否正確 if len(arr) != 3 { return false } //簽名 signByte := j.signFun([]byte(string(arr[0])+"."+string(arr[1]))) if string(signByte) != arr[2] { return false } return true }
這個(gè)文件就已經(jīng)把 JWT 的核心給寫好了,現(xiàn)在只需要根據(jù)你想要的加密算法進(jìn)行填充就好了。
下面我們就去實(shí)現(xiàn)一個(gè)最簡(jiǎn)單的 RS256 算法,新建一個(gè) bs.go 文件,內(nèi)容如下:
package jwt import ( "crypto/sha256" "encoding/base64" "fmt" ) func NewRS256() IJwt { jwtM := Jwt{} //Sha256 jwtM.SetSignFunc(func(bytes []byte) string { h := sha256.New() h.Write(bytes) return fmt.Sprintf("%x",h.Sum(nil)) }) //base64 jwtM.SetEncodeFunc(func(bytes []byte) string { return base64.URLEncoding.EncodeToString(bytes) }) return &jwtM }
我這里 header 和 payload 采用 base64 去加密,簽名采用 sha256 當(dāng)然這種算法生成的 JWT 很容易被人串改模仿,不能用于生產(chǎn)的。
看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝您對(duì)億速云的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。