HTTP 是無狀態的協議,服務器與瀏覽器爲了進行會話跟蹤,必須主動的去維護一個狀態,這個狀態用於告知服務端先後兩個請求是否來自同一瀏覽器。而這個狀態須要經過 cookie 或者 session 去實現。html
Cookie是由HTTP服務器設置的,保存在瀏覽器中。服務器經過Set-Cookie
響應頭字段來指示瀏覽器保存Cookie, 瀏覽器經過Cookie請求頭字段來告訴服務器以前的狀態。 Cookie中包含若干個鍵值對,每一個鍵值對能夠設置過時時間。cookie 是不可跨域的。git
屬性 | 說明 |
---|---|
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 能夠有下面三種值:github
以前默認是 None 的,Chrome80 後默認是 Lax。web
接下來看下從 None 改爲 Lax 到底影響了哪些地方的 Cookies 的發送?直接來一個圖表:
有兩點要注意的地方:redis
若是你想加 SameSite=none 屬性,那麼該 Cookie 就必須同時加上 Secure 屬性,表示只有在 HTTPS 協議下該 Cookie 纔會被髮送。數據庫
IOS 12 的 Safari 以及老版本的一些 Chrome 會把 SameSite=none 識別成 SameSite=Strict,因此服務端必須在下發 Set-Cookie 響應頭時進行 User-Agent 檢測,對這些瀏覽器不下發 SameSite=none 屬性json
HTTP客戶端軟件(包括curl、Node.js)均可以發送任意的HTTP請求,能夠設置任何頭字段。Cookie是能夠被篡改的!且Cookie是明文傳輸的。跨域
存儲位置:session 是基於 cookie 實現的,session 存儲在服務器端,sessionId 會被存儲到客戶端的cookie 中。Session 能夠存儲在HTTP服務器的內存中,也能夠存在內存數據庫(如redis)中, 對於重量級的應用甚至能夠存儲在數據庫中。
認證流程瀏覽器
認證:驗證當前用戶的身份。
受權:受權第三方應用使用用戶某些資源的權限。
憑證:用來標記訪問者身份的證書緩存
訪問資源接口(API)時所須要的資源憑證。
JSON Web Token(JWT)是跨域身份驗證方案。
簡單 token 的組成: uid
(用戶惟一的身份標識)、time
(當前時間的時間戳)、sign
(簽名)
特色:
認證流程:
Session 能夠記錄會話信息,Token 不會存儲會話信息。
安全性:Token 安全性比 Session 好
前提:用cookie存儲永久數據存在如下幾個問題:1.大小:cookie的大小被限制在4KB。
2.帶寬:cookie是隨HTTP事務一塊兒被髮送的,所以會浪費一部分發送cookie時使用的帶寬。
3.複雜性:要正確的操縱cookie是很困難的。只能用document.cookie = '...' 來修改
針對這些問題,在HTML5中,從新提供了一種在客戶端本地保存數據的功能,它就是Web Storage。這是HTML5中新增的一個功能,使用它能夠在客戶端本地創建一個數據庫,減輕了服務器端的負擔,加快了訪問數據的速度。
WebStorage提供了兩種API:localStorage(本地存儲)和sessionStorage(會話存儲)。
localStorage:只要在同一源下(協議+主機名+端口)就能讀取/修改到同一份localStorage數據。
sessionStorage:比localStorage更嚴苛,除了協議、主機名、端口外,還要求在同一窗口(也就是瀏覽器的標籤頁)下。
localStorage:存在本地,永久保存。
sessionStorage:只要關閉瀏覽器(也包括瀏覽器的標籤頁),就會被清空。
localStorage:經常使用於長期登陸(+判斷用戶是否已登陸),適合長期保存在本地的數據。
sessionStorage:敏感帳號一次性登陸;
如下都以localStorage舉例。
爲標準的鍵值對(Key-Value)數據類型,簡單易擴展,只能存儲字符串類型。
對於複雜的對象可使用ECMAScript提供的JSON對象的stringify和parse來處理。
對於圖片能夠轉換成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了。
(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 屬性