41.前端鑒權(quán)(2021-07-26)

1.cookie

在前端請(qǐng)求網(wǎng)絡(luò)資源或是后端接口時(shí),請(qǐng)求頭 Headers 里都會(huì)帶上當(dāng)前域下的 cookie 信息,服務(wù)端通過檢測(cè)請(qǐng)求頭內(nèi)的 cookie 判斷當(dāng)前用戶的登錄狀態(tài)是否過期,或是 cookie 是否錯(cuò)誤,來判斷當(dāng)前用戶是否能成功返回響應(yīng)。這個(gè)過程大概是,前端請(qǐng)求登錄接口,后端驗(yàn)證用戶名和密碼是否正確。在正確的情況下服務(wù)端 Set-Cookie ,參數(shù)大致是域名、有效時(shí)間、secure (是否 HTTPS ) 等,種下 cookie 之后,瀏覽器就會(huì)在指定域下添加相應(yīng)的 cookie 信息

2.session

session 是另一種記錄服務(wù)器和客戶端會(huì)話狀態(tài)的機(jī)制。session存儲(chǔ)在服務(wù)器端,該會(huì)話對(duì)應(yīng)的key即sessionId會(huì)被存儲(chǔ)到客戶端的cookie中。

Cookie 和 Session 對(duì)比

安全性: Session 比 Cookie 安全,Session 是存儲(chǔ)在服務(wù)器端的,Cookie 是存儲(chǔ)在客戶端的。

存取值的類型:Cookie只支持存字符串?dāng)?shù)據(jù),想要設(shè)置其他類型的數(shù)據(jù),需要將其轉(zhuǎn)換成字符串,Session 可以存任意數(shù)據(jù)類型。

有效期: Cookie可設(shè)置為長(zhǎng)時(shí)間保持,比如我們經(jīng)常使用的默認(rèn)登錄功能,Session 一般失效時(shí)間較短,客戶端關(guān)閉(默認(rèn)情況下)或者 Session 超時(shí)都會(huì)失效。

存儲(chǔ)大小: 單個(gè) Cookie 保存的數(shù)據(jù)不能超過 4K,Session 可存儲(chǔ)數(shù)據(jù)遠(yuǎn)高于 Cookie,但是當(dāng)訪問量過多,會(huì)占用過多的服務(wù)器資源。

session缺點(diǎn):

占資源: 每個(gè)經(jīng)過認(rèn)證的用戶都要存放session到內(nèi)存中,而隨著認(rèn)證用戶的增多,服務(wù)端的開銷較大。

CSRF攻擊:基于cookie來進(jìn)行用戶識(shí)別時(shí),用戶cookie如果被截獲,就容易受到跨站請(qǐng)求偽造的攻擊。

3.token

Token 是服務(wù)器生成的一串隨機(jī)字符串或者一個(gè) json 串,用于客戶端進(jìn)行資源請(qǐng)求的令牌。當(dāng)我們調(diào)用登錄接口之后,服務(wù)端返回給前端一個(gè) Token ,之后存儲(chǔ) Token 到本地環(huán)境,每次前端請(qǐng)求接口的時(shí)候,都需要在請(qǐng)求頭里帶上 Token 信息,并且 Token 可以在服務(wù)端設(shè)置過期時(shí)間。Token 過期之后,前端在請(qǐng)求失敗回調(diào) 406(前后端協(xié)商好錯(cuò)誤碼)之后重新跳轉(zhuǎn)到登錄界面進(jìn)行鑒權(quán)。

Token 和 Session 的區(qū)別

Session 是一種記錄服務(wù)器和客戶端會(huì)話狀態(tài)的機(jī)制,使服務(wù)端有狀態(tài)化,可以記錄會(huì)話信息。而 Token 是令牌,訪問資源接口(API)時(shí)所需要的資源憑證。Token 使服務(wù)端無狀態(tài)化,不會(huì)存儲(chǔ)會(huì)話信息。Session 和 Token 并不矛盾,作為身份認(rèn)證 Token 安全性比 Session 好,因?yàn)槊恳粋€(gè)請(qǐng)求都有簽名還能防止監(jiān)聽以及重放攻擊,而 Session 就必須依賴鏈路層來保障通訊安全了。如果你需要實(shí)現(xiàn)有狀態(tài)的會(huì)話,仍然可以增加 Session 來在服務(wù)器端保存一些狀態(tài)。

所謂 Session 認(rèn)證只是簡(jiǎn)單的把 User 信息存儲(chǔ)到 Session 里,因?yàn)?SessionID 的不可預(yù)測(cè)性,暫且認(rèn)為是安全的。而 Token ,如果指的是 OAuth Token 或類似的機(jī)制的話,提供的是 認(rèn)證 和 授權(quán) ,認(rèn)證是針對(duì)用戶,授權(quán)是針對(duì) App 。其目的是讓某 App 有權(quán)利訪問某用戶的信息。

4.JWT

JSON Web Token(簡(jiǎn)稱JWT)是目前最流行的跨域認(rèn)證解決方案,是一種認(rèn)證授權(quán)機(jī)制,是一種基于 JSON 的開放標(biāo)準(zhǔn)。

JWT 認(rèn)證流程:

用戶輸入用戶名/密碼登錄,服務(wù)端認(rèn)證成功后,會(huì)返回給客戶端一個(gè) JWT。

客戶端將 jwt 保存到本地,當(dāng)用戶希望訪問一個(gè)受保護(hù)的路由或者資源的時(shí)候,需要請(qǐng)求頭的 Authorization 字段中使用 Bearer 模式添加 JWT 。

服務(wù)端的保護(hù)路由將會(huì)檢查請(qǐng)求頭 Authorization 中的 JWT 信息,如果合法,則允許訪問。因?yàn)?JWT 內(nèi)部包含了一些用戶信息,因此減少了需要查詢數(shù)據(jù)庫(kù)的需要。

JWT 的使用方式

1、存放在cookie中

當(dāng)用戶希望訪問一個(gè)受保護(hù)的路由或者資源的時(shí)候,可以把它放在 Cookie 里面自動(dòng)發(fā)送,但是這樣不能跨域。

2、存放在localstorage中,添加到header中發(fā)送

請(qǐng)求時(shí)放在 HTTP 請(qǐng)求頭信息的 Authorization 字段里,使用 Bearer 模式添加 JWT。

Authorization: Bearer <token>

3、通過接口參數(shù)

可以把 JWT 放在 POST 請(qǐng)求的數(shù)據(jù)體里,或者通過 URL 的 queryString 傳輸。

自定義Token 和 JWT 的關(guān)系

相同點(diǎn): 都是訪問資源的令牌,都可以記錄用戶的信息,都是使服務(wù)端無狀態(tài)化,都是只有驗(yàn)證成功后,客戶端才能訪問服務(wù)端上受保護(hù)的資源

區(qū)別:服務(wù)端驗(yàn)證客戶端發(fā)來的token信息要進(jìn)行數(shù)據(jù)的查詢操作;JWT驗(yàn)證客戶端發(fā)來的token信息就不用, 在服務(wù)端使用密鑰校驗(yàn)就可以,不用數(shù)據(jù)庫(kù)的查詢。

使用 cookie 注意點(diǎn)

? 因?yàn)榇鎯?chǔ)在客戶端,容易被客戶端篡改,使用前需要驗(yàn)證合法性

? 不要存儲(chǔ)敏感數(shù)據(jù),比如用戶密碼,賬戶余額

? 使用 httpOnly 在一定程度上提高安全性

? 盡量減少 cookie 的體積,能存儲(chǔ)的數(shù)據(jù)量不能超過 4kb

? 設(shè)置正確的 domain 和 path,減少數(shù)據(jù)傳輸

? cookie 無法跨域,子域名可以訪問父域名

? 一個(gè)瀏覽器針對(duì)一個(gè)網(wǎng)站最多存 20 個(gè)Cookie,瀏覽器一般只允許存放 300 個(gè)Cookie

? 移動(dòng)端對(duì) cookie 的支持不是很好,而 session 一般基于 cookie 實(shí)現(xiàn),所以移動(dòng)端常用的是 token

使用 session 注意點(diǎn)

? 用戶同時(shí)在線量較多時(shí),session 存儲(chǔ)在服務(wù)器會(huì)占據(jù)較多內(nèi)存,需要定期清理過期 的 session

? 當(dāng)網(wǎng)站采用集群部署的時(shí)候,會(huì)遇到多臺(tái) web 服務(wù)器之間如何做 session 共享的問題。因?yàn)?session是由單個(gè)服務(wù)器創(chuàng)建的,處理用戶請(qǐng)求的服務(wù)器不一定是 那個(gè)創(chuàng)建 session 的服務(wù)器,那么該服務(wù)器就無法拿到之前已經(jīng)放入到 session 中的登錄憑證之類的信息了。

? 當(dāng)多個(gè)應(yīng)用要共享 session時(shí),因?yàn)椴煌膽?yīng)用可能部署的主機(jī)不一樣需要在各個(gè)應(yīng)用做好 cookie 跨域的處理。

? sessionId 是存儲(chǔ)在 cookie 中的,假如瀏覽器禁止 cookie 或不支持 cookie ,一般會(huì)把 sessionId 跟在 url 參數(shù)后面即重寫 url,所以 session 不一定非得需要靠 cookie 實(shí)現(xiàn)

使用 token 注意點(diǎn)

? 如果你認(rèn)為用數(shù)據(jù)庫(kù)來存儲(chǔ) token會(huì)導(dǎo)致查詢時(shí)間太長(zhǎng),可以選擇放在 內(nèi)存當(dāng)中,比如 redis 很適合你對(duì) token 查詢的需求。

? token 完全由應(yīng)用管理,所以它可以避開同源策略

? token 可以避免 CSRF 攻擊(因?yàn)椴恍枰?cookie 了)

? 移動(dòng)端對(duì) cookie 的支持不是很好,而 session 需要基于 cookie 實(shí)現(xiàn),所以移動(dòng)端常用的是 token

使用 JWT 時(shí)需要考慮的問題

? JWT 默認(rèn)是不加密,但也是可以加密的。生成原始 Token 以后,可以用密鑰再加密一次。

? JWT 不加密的情況下,不能將秘密數(shù)據(jù)寫入 JWT。

? JWT 不僅可以用于認(rèn)證,也可以用于交換信息。有效使用 JWT,可以降低服務(wù)器查詢數(shù)據(jù)庫(kù)的次數(shù)。

? JWT 最大的優(yōu)勢(shì)是服務(wù)器不再需要存儲(chǔ)Session,使得服務(wù)器認(rèn)證鑒權(quán)業(yè)務(wù)可以方便擴(kuò)展。但這也是 JWT 最大的缺點(diǎn):由于服務(wù)器不需要存儲(chǔ) Session 狀態(tài),因此使用過程中無法廢棄某個(gè) Token 或者更改 Token 的權(quán)限。也就是說一旦 JWT 簽發(fā)了,到期之前就會(huì)始終有效,除非服務(wù)器部署額外的邏輯。

? JWT 本身包含了認(rèn)證信息,一旦泄露,任何人都可以獲得該令牌的所有權(quán)限。為了減少盜用,JWT的有效期應(yīng)該設(shè)置得比較短。對(duì)于一些比較重要的權(quán)限,使用時(shí)應(yīng)該再次對(duì)用戶進(jìn)行認(rèn)證。

? JWT 適合一次性的命令認(rèn)證,頒發(fā)一個(gè)有效期極短的JWT,即使暴露了危險(xiǎn)也很小由 于每次操作都會(huì)生成新的 JWT,因此也沒必要保存 JWT,真正實(shí)現(xiàn)無狀態(tài)。

? 為了減少盜用,JWT 不應(yīng)該使用 HTTP 協(xié)議明碼傳輸,要使用 HTTPS 協(xié)議傳輸。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容