Gin 教程叕來了(說好的大結局呢?),此次主要是來講明 JWT
存在的一些問題和解決方案。若是你還不知道 JWT
是什麼,建議瞭解一下,也能夠翻翻前面的文章看看。git
上次寫 JWT
的時候,和羣裏的小夥伴討論,有小夥伴提出了一些問題,用戶修改密碼或者註銷帳戶怎麼辦?github
是啊,怎麼辦?redis
咱們都知道 JWT
是否有效,靠的是失效時間,並且服務器不對用戶 JWT
進行保存,也就是一旦簽發了的 JWT
,服務器失去了對其的控制權,只能等其過時而失效。若是這樣,那麼用戶修改密碼或者註銷以後,以前的 JWT
仍舊還能夠使用,那麼就會帶來安全風險。數據庫
因而乎,我默默的打開了百(gu)度(ge)瀏覽器
🙄🙄🙄🙄🙄🙄安全
大家爲何要把 JWT
存在 redis
裏?服務器
這是什麼操做?一旦服務器去保存 JWT
,還用什麼 JWT
?普通 token
就徹底能夠了啊,何須畫蛇添足。ui
以上就是咱們在使用 JWT
的時候產生的問題。加密
既然有了問題,就要解決。spa
再次回顧一下 JWT
的使用流程。
瀏覽器發出登陸請求,將帳號和密碼提交到服務器;
服務器建立 JWT
而且加密(並非所有加密,僅僅加密 VERIFY SIGNATURE
);
將 JWT
返回瀏覽器;
訪問須要受權的接口,將 JWT
攜帶在Header;
校驗 JWT
,而且從 JWT
獲取 JWT
;
響應瀏覽器。
上面的六個步驟就是 JWT
使用的過程。服務器只作了兩步,生成 JWT
和校驗 JWT
。而咱們解決上述提出的問題,就在服務器端解決。
咱們都知道在加密的時候服務器端會保存一個密鑰,而校驗解密的時候就須要這個密鑰,這個密鑰就是咱們解決該問題的 KEY 。
若是咱們把密鑰設成動態的,用戶密碼修改或者註銷的時候,該密鑰就會發生改變,那麼以前簽發的 JWT
沒法使用新的密鑰來解密了,也就意味着以前的密鑰已經失效了。而這個動態密鑰應該保證獨立,每一個用戶的密鑰應該是不同的,該用戶的密鑰只負責該用戶的 JWT
。
因而乎,問題彷佛已經解決了,咱們能夠在數據庫用戶表中設置一個單獨的字段來標識,每次發生密碼修改或者帳號註銷的時候,只須要修改該字段就能夠保證以前的JWT
失效。或者使用用戶的密碼做爲密鑰。
UserHandler.go
// 經過密碼和保留字段加密
var jwtSecret = []byte(config.Secret + u.Password)
token, err := tokenClaims.SignedString(jwtSecret)
複製代碼
其中 config.Secret
是咱們服務器上的固定密鑰。
Auth.go
// 分割出來載體
payload := strings.Split(token, ".")
bytes, e := jwt.DecodeSegment(payload[1])
if e != nil {
println(e.Error())
}
content := ""
for i := 0; i < len(bytes); i++ {
content += string(bytes[i])
}
split := strings.Split(content, ",")
id := strings.SplitAfter(split[2], ":")
i := strings.Split(id[1], "\\u")
i = strings.Split(i[1], "\"")
ID, err := strconv.Atoi(i[0])
if err != nil {
println(err.Error())
}
user := model.User{}
user.ID = uint(ID)
u := model.User.QueryById(user)
jwtToken, err := jwt.ParseWithClaims(token, &jwt.StandardClaims{},
func(token *jwt.Token) (i interface{}, e error) {
return []byte(config.Secret + u.Password), nil
})
複製代碼
這裏就不展現所有代碼了。你們能夠看 Github gin_jwt_2 分支上查看。
歡迎各位大佬關注。