互聯(lián)網(wǎng)發(fā)展到現(xiàn)在已經(jīng)到了一個(gè)非常成熟的時(shí)代,所以不再是一個(gè)你寫(xiě)一個(gè)靜態(tài)網(wǎng)站就可以進(jìn)行瘋狂盈利的時(shí)代了。現(xiàn)在對(duì)產(chǎn)品有著很多的要求掂僵,健壯性稿辙,安全性這些都是必不可少的昆码。前兩篇也說(shuō)過(guò)了現(xiàn)在公司一般用戶登錄成功會(huì)給前端返回token,前端訪問(wèn)接口請(qǐng)求數(shù)據(jù)需要攜帶token進(jìn)行身份驗(yàn)證邻储。我們一直說(shuō)token赋咽,那究竟什么是token?token其實(shí)就是一個(gè)令牌吨娜,是服務(wù)端生成的一串字符串脓匿,解析可以得到用戶信息。
因?yàn)?b>HTTP是一種無(wú)狀態(tài)協(xié)議宦赠,所以是沒(méi)辦法記住用戶的登錄狀態(tài)的陪毡。所以客戶端每次請(qǐng)求都需要驗(yàn)證身份,最早的解決方案是:當(dāng)用戶請(qǐng)求登錄成功勾扭,在服務(wù)端生成一條記錄毡琉,然后把記錄id發(fā)送給客戶端,客戶端收到以后把這個(gè)id存儲(chǔ)在cookie里妙色,下次該用戶再次向服務(wù)端發(fā)送請(qǐng)求的時(shí)候桅滋,可以帶上這個(gè)cookie,這樣服務(wù)端會(huì)驗(yàn)證一下cookie里的信息身辨,看能不能在服務(wù)端這里找到對(duì)應(yīng)的記錄丐谋,如果可以,說(shuō)明用戶已經(jīng)通過(guò)了身份驗(yàn)證煌珊,就把用戶請(qǐng)求的數(shù)據(jù)返回給客戶端笋鄙。其實(shí)這種方案就是利用session,id值其實(shí)就是sessionid。那我們既然可以使用session進(jìn)行身份驗(yàn)證怪瓶,我們?yōu)槭裁催€要選擇使用token呢萧落?
1.session是需要空間進(jìn)行存儲(chǔ)的肯腕,如果是多服務(wù)器session需要同步信息暑认,但是token在服務(wù)器是可以不需要存儲(chǔ)用戶信息的柿隙。
2.token可以使用瀏覽器的localStorge等骑疆,APP也可以使用自帶數(shù)據(jù)庫(kù)存儲(chǔ)字符串。且不會(huì)出現(xiàn)cookies出現(xiàn)跨域問(wèn)題许布。
3.token可以用JWT來(lái)攜帶部分不太敏感的信息比如用戶ID等兴革,服務(wù)器只要解密token即可使用部分信息。
使用token驗(yàn)證機(jī)制講完了蜜唾,那我們需要知道我們使用token驗(yàn)證的整個(gè)流程:
?1.當(dāng)用戶登錄成功之后, 服務(wù)器端就會(huì)通過(guò)指定算法生成一個(gè)?token杂曲,過(guò)期時(shí)間48h,可以將token?存儲(chǔ)在redis袁余,再將這個(gè)token值返回給客戶端擎勘;
2.客戶端拿到?token?值之后,進(jìn)行保存;
?3.當(dāng)客戶端調(diào)用接口請(qǐng)求數(shù)據(jù)時(shí),就會(huì)攜帶token值發(fā)送給服務(wù)器颖榜;
4.服務(wù)器接收到客戶端的請(qǐng)求之后,會(huì)取出token值與保存在redis中的token值做對(duì)比棚饵。
5.如果token對(duì)比成功,說(shuō)明用戶處于登錄狀態(tài)掩完,否則表示登錄狀態(tài)失效噪漾,需要用戶重新登陸。用戶每次重新登陸會(huì)刷新token的過(guò)期時(shí)間且蓬。
歡迎關(guān)注我的個(gè)人公眾號(hào):周先生自留地
接下來(lái)我們用代碼來(lái)走一趟整個(gè)流程:
首先我們實(shí)現(xiàn)登錄邏輯欣硼,這套沒(méi)什么好講的,可以去看看一篇文章:你不知道的前后端分離之交互(2)
用戶首次登錄去數(shù)據(jù)庫(kù)匹配賬號(hào)密碼恶阴,匹配成功會(huì)返回用戶唯一標(biāo)識(shí)uid,account這些基本數(shù)據(jù)分别。接下來(lái)我們需要去使用指定算法生成一個(gè)token
我們通過(guò)用戶app_sid以及account生成一個(gè)簡(jiǎn)單的token:TKN:3:Q:d:8zTEiTJEJ7dee:AOK_H5,然后去redis查詢以這個(gè)簡(jiǎn)單token為鍵值的token是否存在存淫。
如果用戶token已存在redis中,則刪除這個(gè)token沼填。然后生成新的token桅咆。
將新token存儲(chǔ)到redis中,一樣采用鍵名為簡(jiǎn)單token坞笙,鍵值為最終生成的token岩饼。過(guò)期時(shí)間設(shè)置成48h。
到這里我們生成token的操作就全部完善了薛夜〖耄基本流程就是用戶登錄成功會(huì)以app_sid和account先生成一個(gè)簡(jiǎn)單token,去redis查詢?cè)?b>token是否存在梯澜。存在則刪除token寞冯,然后使用特定算法將簡(jiǎn)單token轉(zhuǎn)化成最終的token存儲(chǔ)到redis。然后給前端返回token進(jìn)行存儲(chǔ)。
可以看到我們成功將token返回給前端了∷绷洌現(xiàn)在我們還需要一個(gè)驗(yàn)證token的接口俭茧。因?yàn)槲覀冎苯訉?b>token存儲(chǔ)在redis中,所以接收到前端傳的token漓帚,我們可以直接去redis中查詢token是否存在母债,如果token存在,則代表用戶處于登錄狀態(tài)尝抖,給前端返回?cái)?shù)據(jù)毡们。否則登陸失敗,提示請(qǐng)先登錄昧辽。
前端每次請(qǐng)求通用數(shù)據(jù)接口的時(shí)候衙熔,先驗(yàn)證token的有效性。這樣整套下來(lái)我們就可以實(shí)現(xiàn)基于token的權(quán)限驗(yàn)證奴迅。但是這套邏輯是有缺點(diǎn)的青责,因?yàn)槲覀兪褂?b>token理論上服務(wù)端可以不進(jìn)行存儲(chǔ),直接指定加解密算法取具,我這里由于生成token使用的隨機(jī)算法脖隶,無(wú)法反向解密,所以只能存儲(chǔ)在redis中進(jìn)行處理暇检。其實(shí)我覺(jué)得更好的方案是直接設(shè)計(jì)加解密算法产阱,服務(wù)端使用加密算法生成token返回給前端,前端每次請(qǐng)求通用數(shù)據(jù)接口攜帶token块仆,服務(wù)端直接接收前端的token進(jìn)行反向解密构蹬,如果解密成功則可以得到用戶的uid等基本信息,解密失敗則提示前端請(qǐng)先登錄悔据。這部分在這里我就不多說(shuō)了庄敛,具體可以看看上一篇文章講到的AES加解密。
本篇內(nèi)容到這里結(jié)束了科汗。本篇內(nèi)容代碼后續(xù)整理后會(huì)同步到github中藻烤。歡迎關(guān)注我的個(gè)人公眾號(hào):周先生自留地