Json?web?token(JWT)golang實(shí)現(xiàn)方式
Json web token (JWT)
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.UQmqAUhUrpDVV2ST7mZKyLTomVfg7sYkEjmdDI5XF8Q
三部分構(gòu)成
第一部頭部(header)的作用?????
聲明類型
聲明加密的算法 通常直接使用 HMAC SHA256
{'typ': 'JWT','alg': 'HS256'}
將頭部進(jìn)行base64加密
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
第二部分載荷(payload)
載荷就是存放有效信息的地方:
標(biāo)準(zhǔn)中注冊的聲明
- iss: jwt簽發(fā)者
- sub: jwt所面向的用戶
- aud: 接收jwt的一方
- exp: jwt的過期時(shí)間,這個(gè)過期時(shí)間必須要大于簽發(fā)時(shí)間
- nbf: 定義在什么時(shí)間之前,該jwt都是不可用的.
- iat: jwt的簽發(fā)時(shí)間
- jti: jwt的唯一身份標(biāo)識(shí),主要用來作為一次性token,從而回避重放攻擊
公共的聲明
- 公共的聲明可以添加任何的信息
- 一般添加用戶的相關(guān)信息或其他業(yè)務(wù)需要的必要信息
- 議添加敏感信息,因?yàn)樵摬糠衷诳蛻舳丝山饷?/li>
私有的聲明
私有聲明是提供者和消費(fèi)者所共同定義的聲明,一般不建議存放敏感信息,因?yàn)閎ase64是對稱解密的,意味著該部分信息可以歸類為明文信息
- 舉例:
{"sub": "1234567890","name": "John Doe","admin": true}然后將其進(jìn)行base64加密,得到Jwt的第二部分
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9signature
第三部分簽證(signature)
UQmqAUhUrpDVV2ST7mZKyLTomVfg7sYkEjmdDI5XF8Q
- header (base64后的)
- payload (base64后的)
- secret
- 需要base64加密后的header和base64加密后的payload使用"."連接組成的字符串(頭部在前),
- 然后通過header中聲明的加密方式進(jìn)行加secret組合加密,
- 構(gòu)成了jwt的第三部分
- 舉例
- secret 需要保存在服務(wù)端用來生成token和驗(yàn)證
簽名的目的
- 對頭部以及載荷內(nèi)容進(jìn)行簽名
- 加密算法對于不同的輸入產(chǎn)生的輸出總是不一樣
- 對于兩個(gè)不同的輸入,產(chǎn)生同樣的輸出的概率極其地小
- JWT的頭部中已經(jīng)用alg字段指明加密算法
- 服務(wù)器應(yīng)用對頭部和載荷再次以同樣方法簽名之后發(fā)現(xiàn),自己計(jì)算出來的簽名和接受到的簽名不一樣,說明這個(gè)Token的內(nèi)容被別人動(dòng)過的,我們應(yīng)該拒絕這個(gè)Token,返回一個(gè)HTTP 401 Unauthorized響應(yīng)
- 在JWT中,不應(yīng)該在載荷里面加入任何敏感的數(shù)據(jù),比如用戶的密碼
如何應(yīng)用
一般是在請求頭里加入Authorization,并加上Bearer標(biāo)注
fetch('api/user/1', { headers: {'Authorization': 'Bearer ' + token }})服務(wù)端會(huì)驗(yàn)證token如果驗(yàn)證通過,就會(huì)返回相應(yīng)的資源
Golang 客戶端實(shí)現(xiàn)
調(diào)用包 https://github.com/tutengdihuang/jwt
- 單例模式
var jwtIns *JwtAuth
type JwtAuth struct {
Lock *sync.Mutex
algorithm *jwt.Algorithm
claimsMap map[string]*jwt.Claims //key: userID
}
func GetJwtAuth() *JwtAuth {
if jwtIns == nil {
once := sync.Once{}
once.Do(
func() {
if jwtIns == nil {
jwtIns = new(JwtAuth)
jwtIns.Lock = new(sync.Mutex)
jwtIns.claimsMap = make(map[string]*jwt.Claims)
secret := config_center.GetViperConf().Sub("jwt").GetString("secret")
algorithm := jwt.HmacSha256(secret)
jwtIns.algorithm = &algorithm
}
})
}
return jwtIns
}
- get token
var jwtClaimUserKey = "username"
var jwtClaimUserIdKey = "id"
func (this *JwtAuth) GetToken(userName string, id int) (token string, err error) {
claim := jwt.NewClaim()
claim.Set(jwtClaimUserKey, userName)
claim.Set(jwtClaimUserIdKey, strconv.Itoa(id))
//claim.SetTime("expire", time.Now().Add(30*time.Minute))
idstr := strconv.Itoa(id)
this.Lock.Lock()
defer this.Lock.Unlock()
this.claimsMap[idstr] = claim
token, err = this.algorithm.Encode(claim)
return
}
- validate check
func (this *JwtAuth) Validate(idstr, token string) bool {
this.Lock.Lock()
defer this.Lock.Unlock()
if _, ok := this.claimsMap[idstr]; !ok {
return false
}
if this.algorithm.Validate(token) != nil {
return false
}
return true
}
- token decode
func (this *JwtAuth) TokenDecode(token string) (string, int, error) {
claim, err := this.algorithm.Decode(token)
if err != nil {
return "", 0, err
}
userName, err := claim.Get(jwtClaimUserKey)
if err != nil {
return "", 0, err
}
idStr, err := claim.Get(jwtClaimUserIdKey)
if err != nil {
return "", 0, err
}
id, _ := strconv.Atoi(idStr)
return userName, id, nil
}
- token remove
func (this *JwtAuth) TokenRemove(id string) {
this.Lock.Lock()
defer this.Lock.Unlock()
delete(this.claimsMap, id)
}
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
golang使用http client發(fā)起get和post請求示例
這篇文章主要介紹了golang使用http client發(fā)起get和post請求示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02
Golang中Bit數(shù)組的實(shí)現(xiàn)方式
這篇文章主要介紹了Golang中Bit數(shù)組的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-04-04
xorm根據(jù)數(shù)據(jù)庫生成go model文件的操作
這篇文章主要介紹了xorm根據(jù)數(shù)據(jù)庫生成go model文件的操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12

