一、為什么要用到會(huì)話技術(shù)?
HTTP請求是無狀態(tài)的。在互聯(lián)網(wǎng)發(fā)展之始,Web基本上就是文檔瀏覽,服務(wù)器不需要記錄誰在某短時(shí)間瀏覽了什么內(nèi)容。而經(jīng)過互聯(lián)網(wǎng)的發(fā)展,交互式的Web應(yīng)用興起,無狀態(tài)的請求模式已經(jīng)不能滿足需求了,于是用到了會(huì)話技術(shù)。
二、cookie簡介
1、cookie是一種存儲(chǔ)在用戶本地終端(通常是指瀏覽器)上的數(shù)據(jù)。
2、文件大小不超過4kb
3、數(shù)據(jù)以key-value形式存在
4、可以設(shè)置過期時(shí)間(生存周期)expires。cookie有兩種存儲(chǔ)類型cookie:會(huì)話型和持久型。expires屬性缺省時(shí),為會(huì)話型Cookie,僅保存在客戶端內(nèi)存中,并在用戶關(guān)閉瀏覽器時(shí)失效;持久性Cookie會(huì)保存在用戶的硬盤中,直至生存期到或用戶直接在網(wǎng)頁中單擊“注銷”等按鈕結(jié)束會(huì)話時(shí)才會(huì)失效
5、 cookie由服務(wù)器生成,發(fā)送給瀏覽器,瀏覽器把cookie以kv形式保存到某個(gè)目錄下的文本文件內(nèi),下一次請求同一網(wǎng)站時(shí)會(huì)把該cookie發(fā)送給服務(wù)器。
6、當(dāng)瀏覽器不禁用cookie時(shí),客戶端訪問服務(wù)器時(shí)會(huì)自動(dòng)攜帶cookie。cookie遵循同源策略(域名、端口一致)
三、session簡介
1、session是服務(wù)器端存儲(chǔ)(存儲(chǔ)在內(nèi)存中)的一個(gè)對象,主要用于存儲(chǔ)訪問過服務(wù)器的客戶端用戶信息。當(dāng)服務(wù)器重啟,內(nèi)存會(huì)銷毀,存儲(chǔ)的用戶信息會(huì)消失。
2、工作原理:客戶端用戶使用賬號(hào)、密碼登錄服務(wù)器,如果登錄成功服務(wù)器端會(huì)生成并存儲(chǔ)一個(gè)sessionId(字符串)用來標(biāo)記用戶,同時(shí)會(huì)將sessionId通過cookie返回到客戶端,客戶端將sessionId存儲(chǔ)在cookie中。客戶端再次訪問服務(wù)器時(shí)會(huì)默認(rèn)攜帶cookie中的sessionId(相當(dāng)于通行證/令牌)
3、由②可知session基于cookie。session這種會(huì)話存儲(chǔ)方式方式只適用于客戶端代碼和服務(wù)端代碼運(yùn)行在同一臺(tái)服務(wù)器上(前后端項(xiàng)目協(xié)議、域名、端口號(hào)都一致,即在一個(gè)項(xiàng)目下)
4、 session持久化。用于解決重啟服務(wù)器后session就消失的問題。在數(shù)據(jù)庫中存儲(chǔ)session,而不是存儲(chǔ)在內(nèi)存中。通過包:express-mysql-session
四、token簡介
1、token是在服務(wù)器端生成一串字符串,它存儲(chǔ)在客戶端而服務(wù)器端不存儲(chǔ)token但會(huì)存儲(chǔ)秘鑰。秘鑰通常共有且唯一。
2、標(biāo)準(zhǔn)的token(JWT)由三部分組成:header(頭)、payload(負(fù)載)、signature(簽名)。其中header中記錄了使用的簽名算法,payload中記錄的是用戶信息(根據(jù)需要可設(shè)置任何信息),signature部分是根據(jù)算法+秘鑰+信息計(jì)算得到的簽名。
header.payload.signature

3、token 中的數(shù)據(jù)是明文保存的(只會(huì)用base64編碼),還是可以被別人看到的,所以不能在其中保存像密碼這樣的敏感信息。
4、工作流程:
①客戶端用戶通過賬號(hào)密碼登錄服務(wù)器。
②登錄成功后服務(wù)器端生成token,并通過響應(yīng)主體發(fā)送到客戶端??蛻舳藢⑵浔4嬖赾ookie(sessionStorage、localStorage也都可以進(jìn)行存儲(chǔ))中,服務(wù)器端不存儲(chǔ)token值。
③客戶端下次請求時(shí)會(huì)在headers中添加token字符串。
④服務(wù)器端獲取headers中的token,解析出header和用戶信息。然后對二者重新編碼并使用算法及存儲(chǔ)在服務(wù)器端的秘鑰獲得簽名,并與從客戶端傳來(token中)的簽名對比,如果一致即已登錄否則認(rèn)證失敗。


五、session和token的比較
1、session依賴于cookie,每次客戶端訪問服務(wù)器時(shí)都自動(dòng)攜帶cookie,當(dāng)使用前后端分離項(xiàng)目時(shí),后臺(tái)服務(wù)器不能獲取到sessionId。即session不能跨域。

2、相反,客戶端使用token時(shí),每次訪問都會(huì)在headers中添加token字符串,不借助于cookie。能夠跨域。
# 普通的token
headers.Authorization = 'Bearer ' + token;
#JWT
headers.Authorization = 'JWT' + token;
3、使用session時(shí),服務(wù)器在生成sessionId時(shí),服務(wù)器端也會(huì)存儲(chǔ)sessionId,當(dāng)請求服務(wù)器的用戶增多時(shí),服務(wù)器開銷巨大,同時(shí)嚴(yán)重限制了服務(wù)器的擴(kuò)展能力。比如當(dāng)服務(wù)器使用負(fù)載均衡時(shí),小W使用A登錄了服務(wù)器,訪問B資源時(shí)會(huì)失敗,因?yàn)锽中沒有小W的sessionId。(session sticky 請求黏著A,會(huì)存在A可能掛掉,然后仍然會(huì)轉(zhuǎn)到B)。
只能使用session復(fù)制。麻煩。

如果把session id 集中存儲(chǔ)到一個(gè)地方, 所有的機(jī)器都來訪問這個(gè)地方的數(shù)據(jù), 這樣一來,就不用復(fù)制了, 但是增加了單點(diǎn)失敗的可能性, 倘若負(fù)責(zé)session 的機(jī)器掛了, 所有人都得重新登錄。

4、使用token時(shí),服務(wù)器端不會(huì)存儲(chǔ)token串或簽名,客戶端再次訪問時(shí)會(huì)重新生成簽名和攜帶的對比以校驗(yàn)用戶。服務(wù)器節(jié)省了存儲(chǔ)的空間壓力,但是每次訪問都需要重新計(jì)算簽名。以服務(wù)的計(jì)算時(shí)間換取存儲(chǔ)空間
5、使用token能夠阻止CSRF攻擊