徹底搞懂 Cookie扰才、Session允懂、Token、JWT

什么是認(rèn)證(Authentication)

通俗地講就是驗證當(dāng)前用戶的身份训桶,證明“你是你自己”(比如:你每天上下班打卡累驮,都需要通過指紋打卡,當(dāng)你的指紋和系統(tǒng)里錄入的指紋相匹配時舵揭,就打卡成功)谤专。

互聯(lián)網(wǎng)中的認(rèn)證

  • 用戶名密碼登錄
  • 郵箱發(fā)送登錄鏈接
  • 手機(jī)號接收驗證碼
  • 只要你能收到郵箱/驗證碼,就默認(rèn)你是賬號的主人

什么是授權(quán)(Authorization)

  • 用戶授予第三方應(yīng)用訪問該用戶某些資源的權(quán)限

    • 你在安裝手機(jī)應(yīng)用的時候午绳,APP 會詢問是否允許授予權(quán)限(訪問相冊置侍、地理位置等權(quán)限)
    • 你在訪問微信小程序時,當(dāng)?shù)卿洉r拦焚,小程序會詢問是否允許授予權(quán)限(獲取昵稱蜡坊、頭像、地區(qū)赎败、性別等個人信息)
  • 實現(xiàn)授權(quán)的方式有:cookie秕衙、session、token僵刮、OAuth

什么是憑證(Credentials)

實現(xiàn)認(rèn)證和授權(quán)的前提是需要一種媒介(證書)來標(biāo)記訪問者的身份据忘。

  • 在戰(zhàn)國時期鹦牛,商鞅變法,發(fā)明了照身帖勇吊。照身帖由官府發(fā)放曼追,是一塊打磨光滑細(xì)密的竹板,上面刻有持有人的頭像和籍貫信息汉规。國人必須持有礼殊,如若沒有就被認(rèn)為是黑戶,或者間諜之類的针史。
  • 在現(xiàn)實生活中晶伦,每個人都會有一張專屬的居民身份證,是用于證明持有人身份的一種法定證件悟民。通過身份證坝辫,我們可以辦理手機(jī)卡/銀行卡/個人貸款/交通出行等等,這就是認(rèn)證的憑證射亏。
  • 在互聯(lián)網(wǎng)應(yīng)用中近忙,一般網(wǎng)站(如掘金)會有兩種模式,游客模式和登錄模式智润。游客模式下及舍,可以正常瀏覽網(wǎng)站上面的文章,一旦想要點贊/收藏/分享文章窟绷,就需要登錄或者注冊賬號锯玛。當(dāng)用戶登錄成功后,服務(wù)器會給該用戶使用的瀏覽器頒發(fā)一個令牌(token)兼蜈,這個令牌用來表明你的身份攘残,每次瀏覽器發(fā)送請求時會帶上這個令牌,就可以使用游客模式下無法使用的功能为狸。

什么是 Cookie

HTTP 是無狀態(tài)的協(xié)議(對于事務(wù)處理沒有記憶能力歼郭,每次客戶端和服務(wù)端會話完成時,服務(wù)端不會保存任何會話信息):每個請求都是完全獨立的辐棒,服務(wù)端無法確認(rèn)當(dāng)前訪問者的身份信息病曾,無法分辨上一次的請求發(fā)送者和這一次的發(fā)送者是不是同一個人。所以服務(wù)器與瀏覽器為了進(jìn)行會話跟蹤(知道是誰在訪問我)漾根,就必須主動的去維護(hù)一個狀態(tài)泰涂,這個狀態(tài)用于告知服務(wù)端前后兩個請求是否來自同一瀏覽器。而這個狀態(tài)需要通過 cookie 或者 session 去實現(xiàn)辐怕。

  • cookie存儲在客戶端:cookie 是服務(wù)器發(fā)送到用戶瀏覽器并保存在本地的一小塊數(shù)據(jù)逼蒙,它會在瀏覽器下次向同一服務(wù)器再發(fā)起請求時被攜帶并發(fā)送到服務(wù)器上。
  • cookie是不可跨域的:每個 cookie 都會綁定單一的域名寄疏,無法在別的域名下獲取使用其做,一級域名和二級域名之間是允許共享使用的(靠的是 domain)顶考。
cookie 重要的屬性

什么是 Session

  • session 是另一種記錄服務(wù)器和客戶端會話狀態(tài)的機(jī)制
  • session 是基于 cookie 實現(xiàn)的,session 存儲在服務(wù)器端妖泄,sessionId 會被存儲到客戶端的cookie 中
session 認(rèn)證流程
  • 用戶第一次請求服務(wù)器的時候,服務(wù)器根據(jù)用戶提交的相關(guān)信息艘策,創(chuàng)建對應(yīng)的 Session
  • 請求返回時將此 Session 的唯一標(biāo)識信息 SessionID 返回給瀏覽器
  • 瀏覽器接收到服務(wù)器返回的 SessionID 信息后蹈胡,會將此信息存入到 Cookie 中,同時 Cookie 記錄此 SessionID 屬于哪個域名
  • 當(dāng)用戶第二次訪問服務(wù)器的時候朋蔫,請求會自動判斷此域名下是否存在 Cookie 信息,如果存在自動將 Cookie 信息也發(fā)送給服務(wù)端,服務(wù)端會從 Cookie 中獲取 SessionID锉罐,再根據(jù) SessionID 查找對應(yīng)的 Session 信息号涯,如果沒有找到說明用戶沒有登錄或者登錄失效,如果找到 Session 證明用戶已經(jīng)登錄可執(zhí)行后面操作青扔。

根據(jù)以上流程可知源织,SessionID 是連接 Cookie 和 Session 的一道橋梁,大部分系統(tǒng)也是根據(jù)此原理來驗證用戶登錄狀態(tài)微猖。

Cookie 和 Session 的區(qū)別

  • 安全性:Session 比 Cookie 安全谈息,Session 是存儲在服務(wù)器端的,Cookie 是存儲在客戶端的凛剥。
  • 存取值的類型不同:Cookie 只支持存字符串?dāng)?shù)據(jù)侠仇,想要設(shè)置其他類型的數(shù)據(jù),需要將其轉(zhuǎn)換成字符串犁珠,Session 可以存任意數(shù)據(jù)類型逻炊。
  • 有效期不同: Cookie 可設(shè)置為長時間保持,比如我們經(jīng)常使用的默認(rèn)登錄功能犁享,Session 一般失效時間較短余素,客戶端關(guān)閉(默認(rèn)情況下)或者 Session 超時都會失效。
  • 存儲大小不同: 單個 Cookie 保存的數(shù)據(jù)不能超過 4K饼疙,Session 可存儲數(shù)據(jù)遠(yuǎn)高于 Cookie溺森,但是當(dāng)訪問量過多,會占用過多的服務(wù)器資源窑眯。

什么是 Token(令牌)

Acesss Token
  • 訪問資源接口(API)時所需要的資源憑證屏积。
  • 簡單 token 的組成: uid(用戶唯一的身份標(biāo)識)、time(當(dāng)前時間的時間戳)磅甩、sign(簽名炊林,token 的前幾位以哈希算法壓縮成的一定長度的十六進(jìn)制字符串)。

特點:

  • 服務(wù)端無狀態(tài)化卷要、可擴(kuò)展性好
  • 支持移動端設(shè)備
  • 安全
  • 支持跨程序調(diào)用

token 的身份驗證流程:


  • 客戶端使用用戶名跟密碼請求登錄
  • 服務(wù)端收到請求渣聚,去驗證用戶名與密碼
  • 驗證成功后独榴,服務(wù)端會簽發(fā)一個 token 并把這個 token 發(fā)送給客戶端
  • 客戶端收到 token 以后,會把它存儲起來奕枝,比如放在 cookie 里或者 localStorage 里
  • 客戶端每次向服務(wù)端請求資源的時候需要帶著服務(wù)端簽發(fā)的 token
  • 服務(wù)端收到請求棺榔,然后去驗證客戶端請求里面帶著的 token ,如果驗證成功隘道,就向客戶端返回請求的數(shù)據(jù)

每一次請求都需要攜帶 token症歇,需要把 token 放到 HTTP 的 Header 里。

基于 token 的用戶認(rèn)證是一種服務(wù)端無狀態(tài)的認(rèn)證方式谭梗,服務(wù)端不用存放 token 數(shù)據(jù)忘晤。
用解析 token 的計算時間換取 session 的存儲空間,從而減輕服務(wù)器的壓力激捏,減少頻繁的查詢數(shù)據(jù)庫设塔。

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

Refresh Token

另外一種 token——refresh token

refresh token 是專用于刷新 access token 的 token闰蛔。如果沒有 refresh token,也可以刷新 access token表谊,但每次刷新都要用戶輸入登錄用戶名與密碼钞护,會很麻煩。有了 refresh token爆办,可以減少這個麻煩难咕,客戶端直接用 refresh token 去更新 access token,無需用戶進(jìn)行額外的操作距辆。

Access Token 的有效期比較短余佃,當(dāng) Acesss Token 由于過期而失效時,使用 Refresh Token 就可以獲取到新的 Token跨算,如果 Refresh Token 也失效了爆土,用戶就只能重新登錄了。

Refresh Token 及過期時間是存儲在服務(wù)器的數(shù)據(jù)庫中诸蚕,只有在申請新的 Acesss Token 時才會驗證步势,不會對業(yè)務(wù)接口響應(yīng)時間造成影響,也不需要向 Session 一樣一直保持在內(nèi)存中以應(yīng)對大量的請求背犯。

Token 和 Session 的區(qū)別

Session 是一種記錄服務(wù)器和客戶端會話狀態(tài)的機(jī)制坏瘩,使服務(wù)端有狀態(tài)化,可以記錄會話信息漠魏。而 Token 是令牌倔矾,訪問資源接口(API)時所需要的資源憑證。Token 使服務(wù)端無狀態(tài)化,不會存儲會話信息哪自。

Session 和 Token 并不矛盾丰包,作為身份認(rèn)證 Token 安全性比 Session 好,因為每一個請求都有簽名還能防止監(jiān)聽以及重放攻擊壤巷,而 Session 就必須依賴鏈路層來保障通訊安全了邑彪。如果你需要實現(xiàn)有狀態(tài)的會話,仍然可以增加 Session 來在服務(wù)器端保存一些狀態(tài)胧华。

所謂 Session 認(rèn)證只是簡單的把 User 信息存儲到 Session 里锌蓄,因為 SessionID 的不可預(yù)測性,暫且認(rèn)為是安全的撑柔。而 Token ,如果指的是 OAuth Token 或類似的機(jī)制的話您访,提供的是 認(rèn)證 和 授權(quán) 铅忿,認(rèn)證是針對用戶,授權(quán)是針對 App 灵汪。其目的是讓某 App 有權(quán)利訪問某用戶的信息檀训。這里的 Token 是唯一的。不可以轉(zhuǎn)移到其它 App上享言,也不可以轉(zhuǎn)到其它用戶上峻凫。Session 只提供一種簡單的認(rèn)證,即只要有此 SessionID 览露,即認(rèn)為有此 User 的全部權(quán)利荧琼。是需要嚴(yán)格保密的,這個數(shù)據(jù)應(yīng)該只保存在站方差牛,不應(yīng)該共享給其它網(wǎng)站或者第三方 App命锄。所以簡單來說:如果你的用戶數(shù)據(jù)可能需要和第三方共享,或者允許第三方調(diào)用 API 接口偏化,用 Token 脐恩。如果永遠(yuǎn)只是自己的網(wǎng)站,自己的 App侦讨,用什么就無所謂了驶冒。

什么是 JWT

  • JSON Web Token(簡稱 JWT)是目前最流行的跨域認(rèn)證解決方案。
  • 是一種認(rèn)證授權(quán)機(jī)制韵卤。
  • JWT 是為了在網(wǎng)絡(luò)應(yīng)用環(huán)境間傳遞聲明而執(zhí)行的一種基于 JSON 的開放標(biāo)準(zhǔn)(RFC 7519)骗污。JWT 的聲明一般被用來在身份提供者和服務(wù)提供者間傳遞被認(rèn)證的用戶身份信息,以便于從資源服務(wù)器獲取資源怜俐。比如用在用戶登錄上身堡。
  • 可以使用 HMAC 算法或者是 RSA 的公/私秘鑰對 JWT 進(jìn)行簽名。因為數(shù)字簽名的存在拍鲤,這些傳遞的信息是可信的贴谎。
生成 JWT

jwt.io/www.jsonwebtoken.io/

JWT 的原理
JWT 認(rèn)證流程:
  • 用戶輸入用戶名/密碼登錄汞扎,服務(wù)端認(rèn)證成功后,會返回給客戶端一個 JWT

  • 客戶端將 token 保存到本地(通常使用 localstorage擅这,也可以使用 cookie)

  • 當(dāng)用戶希望訪問一個受保護(hù)的路由或者資源的時候澈魄,需要請求頭的 Authorization 字段中使用Bearer 模式添加 JWT,其內(nèi)容看起來是下面這樣

    <pre class="hljs language-avrasm" style="box-sizing: border-box; font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; font-size: 14px; margin-top: 0px !important; margin-bottom: 1.25rem; overflow: auto; display: block; color: rgb(36, 41, 46); background: rgb(233, 236, 239); padding: 1rem; max-height: 35rem; line-height: 1.5;">Authorization: Bearer復(fù)制代碼</pre>

  • 服務(wù)端的保護(hù)路由將會檢查請求頭 Authorization 中的 JWT 信息仲翎,如果合法痹扇,則允許用戶的行為

  • 因為 JWT 是自包含的(內(nèi)部包含了一些會話信息),因此減少了需要查詢數(shù)據(jù)庫的需要

  • 因為 JWT 并不使用 Cookie 的溯香,所以你可以使用任何域名提供你的 API 服務(wù)而不需要擔(dān)心跨域資源共享問題(CORS)

  • 因為用戶的狀態(tài)不再存儲在服務(wù)端的內(nèi)存中鲫构,所以這是一種無狀態(tài)的認(rèn)證機(jī)制

JWT 的使用方式

客戶端收到服務(wù)器返回的 JWT,可以儲存在 Cookie 里面玫坛,也可以儲存在 localStorage结笨。

  • 方式一

當(dāng)用戶希望訪問一個受保護(hù)的路由或者資源的時候,可以把它放在 Cookie 里面自動發(fā)送湿镀,但是這樣不能跨域炕吸,所以更好的做法是放在 HTTP 請求頭信息的 Authorization 字段里,使用 Bearer 模式添加 JWT勉痴。

 GET /calendar/v1/events
 Host: api.example.com
 Authorization: Bearer <token>
  • 用戶的狀態(tài)不會存儲在服務(wù)端的內(nèi)存中赫模,這是一種 無狀態(tài)的認(rèn)證機(jī)制
  • 服務(wù)端的保護(hù)路由將會檢查請求頭 Authorization 中的 JWT 信息,如果合法蒸矛,則允許用戶的行為瀑罗。
  • 由于 JWT 是自包含的,因此減少了需要查詢數(shù)據(jù)庫的需要
  • JWT 的這些特性使得我們可以完全依賴其無狀態(tài)的特性提供數(shù)據(jù) API 服務(wù)莉钙,甚至是創(chuàng)建一個下載流服務(wù)廓脆。
  • 因為 JWT 并不使用 Cookie ,所以你可以使用任何域名提供你的 API 服務(wù)而不需要擔(dān)心跨域資源共享問題(CORS)
  • 方式二

跨域的時候磁玉,可以把 JWT 放在 POST 請求的數(shù)據(jù)體里停忿。

  • 方式三

通過 URL 傳輸

 http://www.example.com/user?token=xxx

項目中使用 JWT

項目地址: https://github.com/yjdjiayou/jwt-demo

Token 和 JWT 的區(qū)別

相同
  • 都是訪問資源的令牌
  • 都可以記錄用戶的信息
  • 都是使服務(wù)端無狀態(tài)化
  • 都是只有驗證成功后,客戶端才能訪問服務(wù)端上受保護(hù)的資源
區(qū)別
  • Token:服務(wù)端驗證客戶端發(fā)送過來的 Token 時蚊伞,還需要查詢數(shù)據(jù)庫獲取用戶信息席赂,然后驗證 Token 是否有效。
  • JWT:將 Token 和 Payload 加密后存儲于客戶端时迫,服務(wù)端只需要使用密鑰解密進(jìn)行校驗(校驗也是 JWT 自己實現(xiàn)的)即可颅停,不需要查詢或者減少查詢數(shù)據(jù)庫,因為 JWT 自包含了用戶信息和加密的數(shù)據(jù)掠拳。

常見的前后端鑒權(quán)方式

  • Session-Cookie
  • Token 驗證(包括 JWT癞揉,SSO)
  • OAuth2.0(開放授權(quán))

常見的加密算法

哈希算法

哈希算法(Hash Algorithm)又稱散列算法、散列函數(shù)、哈希函數(shù)喊熟,是一種從任何一種數(shù)據(jù)中創(chuàng)建小的數(shù)字“指紋”的方法柏肪。哈希算法將數(shù)據(jù)重新打亂混合,重新創(chuàng)建一個哈希值芥牌。

哈希算法主要用來保障數(shù)據(jù)真實性(即完整性)烦味,即發(fā)信人將原始消息和哈希值一起發(fā)送,收信人通過相同的哈希函數(shù)來校驗原始數(shù)據(jù)是否真實壁拉。

哈希算法通常有以下幾個特點:

  • 正像快速:原始數(shù)據(jù)可以快速計算出哈希值

  • 逆向困難:通過哈希值基本不可能推導(dǎo)出原始數(shù)據(jù)

  • 輸入敏感:原始數(shù)據(jù)只要有一點變動谬俄,得到的哈希值差別很大

  • 沖突避免:很難找到不同的原始數(shù)據(jù)得到相同的哈希值,宇宙中原子數(shù)大約在 10 的 60 次方到 80 次方之間弃理,所以 2 的 256 次方有足夠的空間容納所有的可能溃论,算法好的情況下沖突碰撞的概率很低:

    • 2 的 128 次方為 340282366920938463463374607431768211456,也就是 10 的 39 次方級別
    • 2 的 160 次方為 1.4615016373309029182036848327163e+48痘昌,也就是 10 的 48 次方級別
    • 2 的 256 次方為 1.1579208923731619542357098500869 × 10 的 77 次方蔬芥,也就是 10 的 77 次方

注意

  • 以上不能保證數(shù)據(jù)被惡意篡改,原始數(shù)據(jù)和哈希值都可能被惡意篡改控汉,要保證不被篡改,可以使用RSA 公鑰私鑰方案返吻,再配合哈希值姑子。
  • 哈希算法主要用來防止計算機(jī)傳輸過程中的錯誤,早期計算機(jī)通過前 7 位數(shù)據(jù)第 8 位奇偶校驗碼來保障(12.5% 的浪費效率低)测僵,對于一段數(shù)據(jù)或文件街佑,通過哈希算法生成 128bit 或者 256bit 的哈希值,如果校驗有問題就要求重傳捍靠。

常見問題

使用 cookie 時需要考慮的問題
  • 因為存儲在客戶端沐旨,容易被客戶端篡改,使用前需要驗證合法性
  • 不要存儲敏感數(shù)據(jù)榨婆,比如用戶密碼磁携,賬戶余額
  • 使用 httpOnly 在一定程度上提高安全性
  • 盡量減少 cookie 的體積,能存儲的數(shù)據(jù)量不能超過 4kb
  • 設(shè)置正確的 domain 和 path良风,減少數(shù)據(jù)傳輸
  • cookie 無法跨域
  • 一個瀏覽器針對一個網(wǎng)站最多存 20 個Cookie谊迄,瀏覽器一般只允許存放 300 個Cookie
  • 移動端對 cookie 的支持不是很好,而 session 需要基于 cookie 實現(xiàn)烟央,所以移動端常用的是 token
使用 session 時需要考慮的問題
  • 將 session 存儲在服務(wù)器里面统诺,當(dāng)用戶同時在線量比較多時,這些 session 會占據(jù)較多的內(nèi)存疑俭,需要在服務(wù)端定期的去清理過期的 session
  • 當(dāng)網(wǎng)站采用集群部署的時候粮呢,會遇到多臺 web 服務(wù)器之間如何做 session 共享的問題。因為 session 是由單個服務(wù)器創(chuàng)建的,但是處理用戶請求的服務(wù)器不一定是那個創(chuàng)建 session 的服務(wù)器啄寡,那么該服務(wù)器就無法拿到之前已經(jīng)放入到 session 中的登錄憑證之類的信息了豪硅。
  • 當(dāng)多個應(yīng)用要共享 session 時,除了以上問題这难,還會遇到跨域問題舟误,因為不同的應(yīng)用可能部署的主機(jī)不一樣,需要在各個應(yīng)用做好 cookie 跨域的處理姻乓。
  • sessionId 是存儲在 cookie 中的嵌溢,假如瀏覽器禁止 cookie 或不支持 cookie 怎么辦? 一般會把 sessionId 跟在 url 參數(shù)后面即重寫 url蹋岩,所以 session 不一定非得需要靠 cookie 實現(xiàn)
  • 移動端對 cookie 的支持不是很好赖草,而 session 需要基于 cookie 實現(xiàn),所以移動端常用的是 token
使用 token 時需要考慮的問題
  • 如果你認(rèn)為用數(shù)據(jù)庫來存儲 token 會導(dǎo)致查詢時間太長剪个,可以選擇放在內(nèi)存當(dāng)中秧骑。比如 redis 很適合你對 token 查詢的需求。
  • token 完全由應(yīng)用管理扣囊,所以它可以避開同源策略
  • token 可以避免 CSRF 攻擊(因為不需要 cookie 了)
  • 移動端對 cookie 的支持不是很好乎折,而 session 需要基于 cookie 實現(xiàn),所以移動端常用的是 token
使用 JWT 時需要考慮的問題
  • 因為 JWT 并不依賴 Cookie 的侵歇,所以你可以使用任何域名提供你的 API 服務(wù)而不需要擔(dān)心跨域資源共享問題(CORS)
  • JWT 默認(rèn)是不加密骂澄,但也是可以加密的。生成原始 Token 以后惕虑,可以用密鑰再加密一次坟冲。
  • JWT 不加密的情況下,不能將秘密數(shù)據(jù)寫入 JWT溃蔫。
  • JWT 不僅可以用于認(rèn)證健提,也可以用于交換信息。有效使用 JWT伟叛,可以降低服務(wù)器查詢數(shù)據(jù)庫的次數(shù)私痹。
  • JWT 最大的優(yōu)勢是服務(wù)器不再需要存儲 Session,使得服務(wù)器認(rèn)證鑒權(quán)業(yè)務(wù)可以方便擴(kuò)展统刮。但這也是 JWT 最大的缺點:由于服務(wù)器不需要存儲 Session 狀態(tài)侄榴,因此使用過程中無法廢棄某個 Token 或者更改 Token 的權(quán)限。也就是說一旦 JWT 簽發(fā)了网沾,到期之前就會始終有效癞蚕,除非服務(wù)器部署額外的邏輯。
  • JWT 本身包含了認(rèn)證信息辉哥,一旦泄露桦山,任何人都可以獲得該令牌的所有權(quán)限攒射。為了減少盜用,JWT的有效期應(yīng)該設(shè)置得比較短恒水。對于一些比較重要的權(quán)限会放,使用時應(yīng)該再次對用戶進(jìn)行認(rèn)證。
  • JWT 適合一次性的命令認(rèn)證钉凌,頒發(fā)一個有效期極短的 JWT咧最,即使暴露了危險也很小,由于每次操作都會生成新的 JWT御雕,因此也沒必要保存 JWT矢沿,真正實現(xiàn)無狀態(tài)。
  • 為了減少盜用酸纲,JWT 不應(yīng)該使用 HTTP 協(xié)議明碼傳輸捣鲸,要使用 HTTPS 協(xié)議傳輸。
使用加密算法時需要考慮的問題
  • 絕不要以明文存儲密碼
  • 永遠(yuǎn)使用 哈希算法 來處理密碼闽坡,絕不要使用 Base64 或其他編碼方式來存儲密碼栽惶,這和以明文存儲密碼是一樣的,使用哈希疾嗅,而不要使用編碼外厂。編碼以及加密,都是雙向的過程代承,而密碼是保密的酣衷,應(yīng)該只被它的所有者知道, 這個過程必須是單向的次泽。哈希正是用于做這個的,從來沒有解哈希這種說法席爽, 但是編碼就存在解碼意荤,加密就存在解密。
  • 絕不要使用弱哈现欢停或已被破解的哈希算法玖像,像 MD5 或 SHA1 ,只使用強(qiáng)密碼哈希算法齐饮。
  • 絕不要以明文形式顯示或發(fā)送密碼捐寥,即使是對密碼的所有者也應(yīng)該這樣。如果你需要 “忘記密碼” 的功能祖驱,可以隨機(jī)生成一個新的 一次性的(這點很重要)密碼握恳,然后把這個密碼發(fā)送給用戶。

分布式架構(gòu)下 session 共享方案

session 復(fù)制

任何一個服務(wù)器上的 session 發(fā)生改變(增刪改)捺僻,該節(jié)點會把這個 session 的所有內(nèi)容序列化乡洼,然后廣播給所有其它節(jié)點崇裁,不管其他服務(wù)器需不需要 session ,以此來保證 session 同步

  • 優(yōu)點: 可容錯束昵,各個服務(wù)器間 session 能夠?qū)崟r響應(yīng)拔稳。
  • 缺點: 會對網(wǎng)絡(luò)負(fù)荷造成一定壓力,如果 session 量大的話可能會造成網(wǎng)絡(luò)堵塞锹雏,拖慢服務(wù)器性能巴比。
粘性 session /IP 綁定策略

采用 Ngnix 中的 ip_hash 機(jī)制,將某個ip的所有請求都定向到同一臺服務(wù)器上礁遵,即將用戶與服務(wù)器綁定轻绞。用戶第一次請求時,負(fù)載均衡器將用戶的請求轉(zhuǎn)發(fā)到了 A 服務(wù)器上榛丢,如果負(fù)載均衡器設(shè)置了粘性 session 的話铲球,那么用戶以后的每次請求都會轉(zhuǎn)發(fā)到 A 服務(wù)器上,相當(dāng)于把用戶和 A 服務(wù)器粘到了一塊晰赞,這就是粘性 session 機(jī)制稼病。

  • 優(yōu)點:簡單,不需要對 session 做任何處理掖鱼。
  • 缺點:缺乏容錯性然走,如果當(dāng)前訪問的服務(wù)器發(fā)生故障,用戶被轉(zhuǎn)移到第二個服務(wù)器上時戏挡,他的 session 信息都將失效芍瑞。
  • 適用場景: 發(fā)生故障對客戶產(chǎn)生的影響較小褐墅;服務(wù)器發(fā)生故障是低概率事件拆檬。實現(xiàn)方式: 以 Nginx 為例,在 upstream 模塊配置 ip_hash 屬性即可實現(xiàn)粘性 session妥凳。
session 共享(常用)

使用分布式緩存方案比如 Memcached 竟贯、Redis 來緩存 session,但是要求 Memcached 或 Redis 必須是集群

把 session 放到 Redis 中存儲逝钥,雖然架構(gòu)上變得復(fù)雜屑那,并且需要多訪問一次 Redis ,但是這種方案帶來的好處也是很大的:

  • 實現(xiàn)了 session 共享艘款;
  • 可以水平擴(kuò)展(增加 Redis 服務(wù)器)持际;
  • 服務(wù)器重啟 session 不丟失(不過也要注意 session 在 Redis 中的刷新/失效機(jī)制);
  • 不僅可以跨服務(wù)器 session 共享哗咆,甚至可以跨平臺(例如網(wǎng)頁端和 APP 端)
session 持久化

將 session 存儲到數(shù)據(jù)庫中蜘欲,保證 session 的持久化

  • 優(yōu)點: 服務(wù)器出現(xiàn)問題,session 不會丟失
  • 缺點: 如果網(wǎng)站的訪問量很大晌柬,把 session 存儲到數(shù)據(jù)庫中芒填,會對數(shù)據(jù)庫造成很大壓力呜叫,還需要增加額外的開銷維護(hù)數(shù)據(jù)庫。

只要關(guān)閉瀏覽器 殿衰,session 真的就消失了朱庆?

不對。

對 session 來說闷祥,除非程序通知服務(wù)器刪除一個 session娱颊,否則服務(wù)器會一直保留,程序一般都是在用戶做 log off 的時候發(fā)個指令去刪除 session凯砍。然而瀏覽器從來不會主動在關(guān)閉之前通知服務(wù)器它將要關(guān)閉箱硕,因此服務(wù)器根本不會有機(jī)會知道瀏覽器已經(jīng)關(guān)閉,之所以會有這種錯覺悟衩,是大部分 session 機(jī)制都使用會話 cookie 來保存 session id剧罩,而關(guān)閉瀏覽器后這個 session id 就消失了,再次連接服務(wù)器時也就無法找到原來的 session座泳。

如果服務(wù)器設(shè)置的 cookie 被保存在硬盤上惠昔,或者使用某種手段改寫瀏覽器發(fā)出的 HTTP 請求頭,把原來的 session id 發(fā)送給服務(wù)器挑势,則再次打開瀏覽器仍然能夠打開原來的 session镇防。

恰恰是由于關(guān)閉瀏覽器不會導(dǎo)致 session 被刪除,迫使服務(wù)器為 session 設(shè)置了一個失效時間潮饱,當(dāng)距離客戶端上一次使用 session 的時間超過這個失效時間時来氧,服務(wù)器就認(rèn)為客戶端已經(jīng)停止了活動,才會把 session 刪除以節(jié)省存儲空間香拉。

作者:秋天不落葉 juejin.cn/post/6844904034181070861

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末啦扬,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子凫碌,更是在濱河造成了極大的恐慌扑毡,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件证鸥,死亡現(xiàn)場離奇詭異,居然都是意外死亡勤晚,警方通過查閱死者的電腦和手機(jī)枉层,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赐写,“玉大人鸟蜡,你說我怎么就攤上這事⊥ρ” “怎么了揉忘?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵跳座,是天一觀的道長。 經(jīng)常有香客問我泣矛,道長疲眷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任您朽,我火速辦了婚禮狂丝,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘哗总。我一直安慰自己几颜,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布讯屈。 她就那樣靜靜地躺著蛋哭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪涮母。 梳的紋絲不亂的頭發(fā)上谆趾,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天,我揣著相機(jī)與錄音哈蝇,去河邊找鬼棺妓。 笑死,一個胖子當(dāng)著我的面吹牛炮赦,可吹牛的內(nèi)容都是我干的怜跑。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼吠勘,長吁一口氣:“原來是場噩夢啊……” “哼性芬!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起剧防,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤植锉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后峭拘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體俊庇,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年鸡挠,在試婚紗的時候發(fā)現(xiàn)自己被綠了辉饱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡拣展,死狀恐怖彭沼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情备埃,我是刑警寧澤姓惑,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布褐奴,位于F島的核電站,受9級特大地震影響于毙,放射性物質(zhì)發(fā)生泄漏敦冬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一望众、第九天 我趴在偏房一處隱蔽的房頂上張望匪补。 院中可真熱鬧,春花似錦烂翰、人聲如沸夯缺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽踊兜。三九已至,卻和暖如春佳恬,著一層夾襖步出監(jiān)牢的瞬間捏境,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工毁葱, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留垫言,地道東北人。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓倾剿,卻偏偏與公主長得像筷频,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子前痘,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容