加入星計劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
    • Session
    • Token
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請入駐 產(chǎn)業(yè)圖譜

現(xiàn)代Web認(rèn)證與安全管理:深入理解Cookie、Session與Token

3小時前
91
閱讀需 11 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

Cookie

Cookie最主要的作用就是用于會話管理,當(dāng)用戶登錄一個網(wǎng)站時,服務(wù)器會生成一個包含會話ID的Cookie并發(fā)送給瀏覽器,瀏覽器將這個Cookie保存在本地。此后,每次用戶發(fā)送請求時,瀏覽器都會自動將這個Cookie發(fā)送給服務(wù)器,服務(wù)器通過會話ID識別用戶身份,從而保持用戶的登錄狀態(tài)。Cookie除了用于會話管理,還可以在指客戶端持久存儲,一般使用kv形式保存。

cookie屬性

可以看一下瀏覽器持久化存儲的cookie內(nèi)容:

Name/value 鍵值對,cookie的內(nèi)容。
Domain Domain決定Cookie在哪個域是有效的,也就是決定在向該域發(fā)送請求時是否攜帶此Cookie,Domain的設(shè)置是對子域生效的,如Doamin設(shè)置為 .a.com,則b.a.com和c.a.com均可使用該Cookie,但如果設(shè)置為b.a.com,則c.a.com不可使用該Cookie。Domain參數(shù)必須以點(“.”)開始。
Path Cookie的有效路徑,和Domain類似,也對子路徑生效。
Expires/Max-Age 用于指定Cookie的過期時間。
?HttpOnly 此屬性指定Cookie只能通過HTTP協(xié)議訪問。
Secure Cookie的安全屬性,若設(shè)置為true,則瀏覽器只會在HTTPS和SSL等安全協(xié)議中傳輸此Cookie,不會在HTTP協(xié)議中傳輸此Cookie。
SameSite 該屬性用于限制第三方Cookie,防止跨站請求偽造(CSRF)攻擊。

瀏覽器一般會默認(rèn)限制cookie不支持跨域,如果跨域需要配置合理的CORS策略,即配置白名單。

Session

當(dāng)客戶端第一次訪問服務(wù)器的時候,此時客戶端的請求中不攜帶任何標(biāo)識給服務(wù)器,此時服務(wù)器會新建session標(biāo)識,當(dāng)服務(wù)器進(jìn)行響應(yīng)的時候,服務(wù)器會將session標(biāo)識放到http響應(yīng)頭的Set-Cookie中,以key-value的形式返回給客戶端,例:

SESSIONID=xxx;

客戶在下次訪問服務(wù)端的時候,將sessionid帶上,服務(wù)端根據(jù)sessionid從本地內(nèi)存獲取客戶會話信息。

由于會有越來越多的用戶訪問服務(wù)器,因此服務(wù)端的Session也會越來越多。為防止內(nèi)存溢出,服務(wù)器會把長時間(默認(rèn)30分鐘)沒有活躍的Session從內(nèi)存刪除。如果超過了超時時間沒訪問過服務(wù)器,Session就自動失效了,需要重新登錄。

分布式session

SESSIONID僅存儲在單機(jī)服務(wù)器會有單點問題,一般解決Session在多個服務(wù)器之間的共享問題有幾種方法:

1、Sesson Replication

也就是每臺Web服務(wù)器都保存所有用戶的Session數(shù)據(jù),網(wǎng)絡(luò)開銷大,性能低。

2、Sesson Sticky

基于Nginx的sticky模塊,即讓前置負(fù)載均衡器根據(jù)每次請求的ip/cookie來進(jìn)行請求的轉(zhuǎn)發(fā),保證一個會話中的每次請求都能落到同一臺服務(wù)器上面。

缺陷:如果某臺服務(wù)器宕機(jī),那么它上面存儲的Session數(shù)據(jù)就丟失了,用戶就需要重新進(jìn)行登陸。

負(fù)載均衡器變?yōu)橐粋€有狀態(tài)的節(jié)點,因為他需要保存Session到具體服務(wù)器的映射,和之前無狀態(tài)的節(jié)點相比,內(nèi)存消耗會更大,容災(zāi)方面會更麻煩。

3、Sesson數(shù)據(jù)集群存儲

集中存到外部緩存如Redis中,一般大型系統(tǒng)都會單獨(dú)部署redis緩存集群。

Session和cookie一樣都有可能遭到跨站請求偽造(CSRF)攻擊,一般可以使用token解決,對于敏感操作可以雙重驗證,如用戶登陸和資金轉(zhuǎn)賬使用獨(dú)立密碼。

Token

Token是身份驗證和授權(quán)令牌,具有無狀態(tài)性、跨域支持、安全性等優(yōu)點,但需注意安全傳輸、失效管理等問題。Token安全策略包括使用HTTPS、加密存儲、設(shè)置過期時間等。

常用的jwt?token分為三部分:

1、header:指定簽名算法和令牌類型。

2、payload:也是一個JSON對象,用于存放需要傳遞的數(shù)據(jù),例如用戶的信息uid、權(quán)限等,一般還會攜帶時間戳,用于防止重放攻擊。

JWT推薦了payload中的7個可選官方字段:iss (簽發(fā)人), exp (過期時間), ?aud (接收方)等,另外也可以自己協(xié)商私有字段。

3、Signature:簽名,server根據(jù)header獲取簽名算法,再用公鑰根據(jù)此簽名算法對head+payload 生成簽名,這樣一個token就生成了。

客戶端使用token執(zhí)行會話流程

1、用戶使用用戶名和密碼進(jìn)行登錄,系統(tǒng)驗證用戶身份成功后,生成一個Token并返回給客戶端。

2、客戶端將Token保存在本地,通常是存儲在Cookie或LocalStorage中,在每次發(fā)送請求時在請求頭帶上token。

3、服務(wù)端驗證token,通過后執(zhí)行業(yè)務(wù)操作。

4、如果token非法,返回401給客戶端,客戶端需要執(zhí)行登錄操作。

服務(wù)端如何驗證token

這里就要考慮token如何生成。Token既可以使用對稱加密也可以使用非對稱加密(JWT)生成。對稱加密中Token 中通常只有 userId 和 timestamp,客戶端無法解密token也無法往里面添加內(nèi)容。非對稱加密中客戶端可以使用公鑰解密token獲取用戶信息,也可以使用公鑰打包添加額外信息。

為了安全起見,防止token被攻擊者盜用,token 的有效期不會設(shè)置的太長,這樣就會由于 token過期導(dǎo)致用戶需要重新登錄從而生成新的token。服務(wù)端驗證token過期會返回401,前端重定向到登錄頁面。如何才能做到不需要用戶去頻繁的登錄呢,有下面兩種形式。

1、單token方案

2、雙token方案,Refresh Token機(jī)制

Oauth2認(rèn)證規(guī)范中把之前的那個Token稱為Access Token,業(yè)務(wù)方用這個 Access Token進(jìn)行認(rèn)證鑒權(quán)。而Refresh Token是專門用來在Access Token過期后重新獲取新的Access Token的Token。

Refresh Token的過期時間一般設(shè)置長一點

比如一天,Access Token的過期時間設(shè)置短一點比如30分鐘,這樣可以縮短Access Token的過期時間保證安全,同時又不會因為頻繁過期重新要求用戶登錄。

Access Token每次訪問都要攜帶,因此更容易被盜??;Refresh Token被盜的風(fēng)險遠(yuǎn)小于Access Token。

Token失效與管理

Token是由客戶端保存的,一旦服務(wù)器生成,它就一直有效,直到過期。換句話說,服務(wù)器無法主動讓一個Token失效,除非將Token放入“黑名單”中,這樣每次驗證Token時都需要先檢查這個黑名單。如果Token在黑名單里,就會被認(rèn)為無效。但問題是,黑名單必須保存在服務(wù)器端,這意味著如果要支持服務(wù)器隨時“踢掉”用戶,就相當(dāng)于將服務(wù)變成了“有狀態(tài)”的管理,類似于Session模式。

所以,一般情況下,當(dāng)客戶端登出時,最簡單的方法是直接刪除本地存儲的Token,用戶下次登錄時,服務(wù)器會重新生成一個新的Token。

對于大規(guī)模用戶的系統(tǒng),通常會部署獨(dú)立的認(rèn)證系統(tǒng),并使用如Redis集群這種方式來存儲Session,這樣就能更方便地管理Token的過期和刷新問題。

通常,Token是存放在HTTP請求頭中的Authorization字段,而不是放在Cookie里。這樣做的主要原因是為了解決跨域請求時無法共享Cookie的問題。對于跨域問題,通常需要在服務(wù)器端配置允許來自所有域的請求,這可以通過設(shè)置Access-Control-Allow-Origin: *來實現(xiàn)。

基于token可以實現(xiàn)SSO單點登錄,只需要各個服務(wù)器都使用同一個密鑰對token進(jìn)行加密解密即可。

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

機(jī)械轉(zhuǎn)行IT狗,目前在阿里巴巴淘寶事業(yè)群。日常記錄Linux應(yīng)用開發(fā)、嵌入式操作系統(tǒng)、無線網(wǎng)絡(luò)協(xié)議棧。剛深入使用Java,跟大家一起入門交流。