Gin(十五):JWT使用(續)

Gin 教程叕來了(說好的大結局呢?),此次主要是來講明 JWT 存在的一些問題和解決方案。若是你還不知道 JWT 是什麼,建議瞭解一下,也能夠翻翻前面的文章看看。git

💊問題所在

上次寫 JWT 的時候,和羣裏的小夥伴討論,有小夥伴提出了一些問題,用戶修改密碼或者註銷帳戶怎麼辦?github

是啊,怎麼辦?redis

咱們都知道 JWT 是否有效,靠的是失效時間,並且服務器不對用戶 JWT 進行保存,也就是一旦簽發了的 JWT ,服務器失去了對其的控制權,只能等其過時而失效。若是這樣,那麼用戶修改密碼或者註銷以後,以前的 JWT 仍舊還能夠使用,那麼就會帶來安全風險。數據庫

因而乎,我默默的打開了百(gu)度(ge)瀏覽器

🙄🙄🙄🙄🙄🙄安全

大家爲何要把 JWT 存在 redis 裏?服務器

這是什麼操做?一旦服務器去保存 JWT,還用什麼 JWT ?普通 token 就徹底能夠了啊,何須畫蛇添足。ui

以上就是咱們在使用 JWT 的時候產生的問題。加密

🀄解決問題

既然有了問題,就要解決。spa

再次回顧一下 JWT 的使用流程。

  1. 瀏覽器發出登陸請求,將帳號和密碼提交到服務器;

  2. 服務器建立 JWT 而且加密(並非所有加密,僅僅加密 VERIFY SIGNATURE);

  3. JWT 返回瀏覽器;

  4. 訪問須要受權的接口,將 JWT 攜帶在Header;

  5. 校驗 JWT ,而且從 JWT 獲取 JWT

  6. 響應瀏覽器。

上面的六個步驟就是 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 分支上查看。

我的公衆號

歡迎各位大佬關注。

相關文章
相關標籤/搜索