cookie、session、token
cookie、session產生的背景
HTTP 是無狀態的協議,服務器與瀏覽器為了進行會話跟蹤,必須主動的去維護一個狀態,這個狀態用於告知服務端前後兩個請求是否來自同一瀏覽器。而這個狀態需要通過 cookie 或者 session 去實現。
Cookie 的實現機制
Cookie是由HTTP服務器設置的,保存在瀏覽器中。服務器通過Set-Cookie響應頭字段來指示瀏覽器保存Cookie, 瀏覽器通過Cookie請求頭字段來告訴服務器之前的狀態。 Cookie中包含若干個鍵值對,每個鍵值對可以設置過期時間。cookie 是不可跨域的。
cookie的重要屬性
| 屬性 | 説明 |
|---|---|
| name=value | 鍵值對,設置 Cookie 的名稱及相對應的值,都必須是字符串類型
如果值為 Unicode 字符,需要為字符編碼。 如果值為二進制數據,則需要使用 BASE64 編碼。 |
| domain | 指定 cookie 所屬域名,默認是當前域名 |
| path | 指定 cookie 在哪個路徑(路由)下生效,默認是 '/'。
如果設置為 /abc,則只有 /abc 下的路由可以訪問到該 cookie,如:/abc/read。 |
| maxAge | cookie 失效的時間,單位秒。如果為整數,則該 cookie 在 maxAge 秒後失效。如果為負數,該 cookie 為臨時 cookie ,關閉瀏覽器即失效,瀏覽器也不會以任何形式保存該 cookie 。如果為 0,表示刪除該 cookie 。默認為 -1。
比 expires 好用。 |
| expires | 過期時間,在設置的某個時間點後該 cookie 就會失效。
一般瀏覽器的 cookie 都是默認儲存的,當關閉瀏覽器結束這個會話的時候,這個 cookie 也就會被刪除 |
| secure | 該 cookie 是否僅被使用安全協議傳輸。安全協議有 HTTPS,SSL等,在網絡上傳輸數據之前先將數據加密。默認為false。
當 secure 值為 true 時,cookie 在 HTTP 中是無效,在 HTTPS 中才有效。 |
| httpOnly | 如果給某個 cookie 設置了 httpOnly 屬性,則無法通過 JS 腳本 讀取到該 cookie 的信息,但還是能通過 Application 中手動修改 cookie,所以只是在一定程度上可以防止 XSS 攻擊,不是絕對的安全 |
| SameSite | 可以讓 Cookie 在跨站請求時不會被髮送,從而可以阻止跨站請求偽造攻擊(CSRF)。 |
SameSite
SameSite 可以有下面三種值:
- Strict僅允許一方請求攜帶 Cookie,即瀏覽器將只發送相同站點請求的 Cookie,即當前網頁 URL 與請求目標 URL 完全一致。
- Lax允許部分第三方請求攜帶 Cookie
- None無論是否跨站都會發送 Cookie
之前默認是 None 的,Chrome80 後默認是 Lax。
接下來看下從 None 改成 Lax 到底影響了哪些地方的 Cookies 的發送?直接來一個圖表:
有兩點要注意的地方:
- HTTP 接口不支持 SameSite=none
如果你想加 SameSite=none 屬性,那麼該 Cookie 就必須同時加上 Secure 屬性,表示只有在 HTTPS 協議下該 Cookie 才會被髮送。
- 需要 UA 檢測,部分瀏覽器不能加 SameSite=none
IOS 12 的 Safari 以及老版本的一些 Chrome 會把 SameSite=none 識別成 SameSite=Strict,所以服務端必須在下發 Set-Cookie 響應頭時進行 User-Agent 檢測,對這些瀏覽器不下發 SameSite=none 屬性
Cookie 的安全隱患
HTTP客户端軟件(包括curl、Node.js)都可以發送任意的HTTP請求,可以設置任何頭字段。Cookie是可以被篡改的!且Cookie是明文傳輸的。
session
存儲位置:session 是基於 cookie 實現的,session 存儲在服務器端,sessionId 會被存儲到客户端的cookie 中。Session 可以存儲在HTTP服務器的內存中,也可以存在內存數據庫(如redis)中, 對於重量級的應用甚至可以存儲在數據庫中。
認證流程
cookie和session的區別
- 安全性: Session 比 Cookie 安全,Session 是存儲在服務器端的,Cookie 是存儲在客户端的。
- 存取值的類型不同:Cookie 只支持存字符串數據,Session 可以存任意數據類型。
- 有效期不同: Cookie 可設置為長時間保持,Session 一般失效時間較短,客户端關閉(默認情況下)或者 Session 超時都會失效。
- 存儲大小不同: 單個 Cookie 保存的數據不能超過 4K,Session 可存儲數據遠高於 Cookie,但是當訪問量過多,會佔用過多的服務器資源。
認證、授權、憑證
認證:驗證當前用户的身份。
授權:授權第三方應用使用用户某些資源的權限。
憑證:用來標記訪問者身份的證書
token
訪問資源接口(API)時所需要的資源憑證。
JSON Web Token(JWT)是跨域身份驗證方案。
簡單 token 的組成: uid(用户唯一的身份標識)、time(當前時間的時間戳)、sign(簽名)
特點:
- 服務端無狀態化、可擴展性好
- 支持移動端設備
- 安全
- 支持跨程序調用
認證流程:
token和session的區別
Session 可以記錄會話信息,Token 不會存儲會話信息。
安全性:Token 安全性比 Session 好
webStorage
背景
前提:用cookie存儲永久數據存在以下幾個問題:1.大小:cookie的大小被限制在4KB。
2.帶寬:cookie是隨HTTP事務一起被髮送的,因此會浪費一部分發送cookie時使用的帶寬。
3.複雜性:要正確的操縱cookie是很困難的。只能用document.cookie = '...' 來修改
針對這些問題,在HTML5中,重新提供了一種在客户端本地保存數據的功能,它就是Web Storage。這是HTML5中新增的一個功能,使用它可以在客户端本地建立一個數據庫,減輕了服務器端的負擔,加快了訪問數據的速度。
WebStorage提供了兩種API:localStorage(本地存儲)和sessionStorage(會話存儲)。
localStorage 與 sessionStorage 的不同:
作用範圍:
localStorage:只要在同一源下(協議+主機名+端口)就能讀取/修改到同一份localStorage數據。
sessionStorage:比localStorage更嚴苛,除了協議、主機名、端口外,還要求在同一窗口(也就是瀏覽器的標籤頁)下。
生存週期:
localStorage:存在本地,永久保存。
sessionStorage:只要關閉瀏覽器(也包括瀏覽器的標籤頁),就會被清空。
應用場景:
localStorage:常用於長期登錄(+判斷用户是否已登錄),適合長期保存在本地的數據。
sessionStorage:敏感賬號一次性登錄;
相同:
以下都以localStorage舉例。
數據結構:
為標準的鍵值對(Key-Value)數據類型,簡單易擴展,只能存儲字符串類型。
對於複雜的對象可以使用ECMAScript提供的JSON對象的stringify和parse來處理。
- JSON.stringify()將其json對象轉為字符串。
- JSON.parse()將字符串轉為json對象格式。
對於圖片可以轉換成DataUrl(base64)。
存儲大小:
一般都是:5MB
存儲位置:
都保存在客户端,不與服務器進行交互通信。
使用方法:
寫入:
//寫入a字段
localStorage["a"]='1';
//寫入b字段
localStorage.b='2';
//寫入c字段
localStorage.setItem("c",'3'); //推薦
獲取:getItem (key)
localStorage.getItem(key)
刪除:
將localStorage的所有內容清除:
localStorage.clear()
將localStorage中的某個鍵值對刪除:
localStorage.removeItem(key);
localStorage的鍵獲取:
key()方法,向其中出入索引即可獲取對應的鍵
localStorage.setItem("a","red");
localStorage.setItem("b","black");
for (let i =0;i<localStorage.length;i++){
console.log(localStorage.key(i));
}
問題:
在iPhone/iPad上有時設置setItem()時會出現詭異的QUOTA_EXCEEDED_ERR錯誤,這時一般在setItem之前,先removeItem()就ok了。
WebStorage的優點:
(1)存儲空間更大:cookie為4KB,而WebStorage是5MB;
(2)節省網絡流量:WebStorage不會傳送到服務器,存儲在本地的數據可以直接獲取,也不會像cookie一樣每次請求都會傳送到服務器,所以減少了客户端和服務器端的交互,節省了網絡流量;
(3)對於那種只需要在用户瀏覽一組頁面期間保存而關閉瀏覽器後就可以丟棄的數據,sessionStorage會非常方便;
(4)快速顯示:有的數據存儲在WebStorage上,再加上瀏覽器本身的緩存。獲取數據時可以從本地獲取會比從服務器端獲取快得多,所以速度更快;
(5)安全性:WebStorage不會隨着HTTP header發送到服務器端,所以安全性相對於cookie來説比較高一些,不會擔心截獲,但是仍然存在偽造問題;
參考文章:菜鳥教程—localstorage 必知必會
參考文章:cookies、sessionStorage和localStorage解釋及區別
參考文章:傻傻分不清之 Cookie、Session、Token、JWT
參考文章:Cookie/Session 的機制與安全
參考文章:瀏覽器系列之 Cookie 和 SameSite 屬性