十年網(wǎng)站開發(fā)經(jīng)驗 + 多家企業(yè)客戶 + 靠譜的建站團隊
量身定制 + 運營維護+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
本文轉(zhuǎn)載自微信公眾號「愛笑的架構師」,作者雷小帥 。轉(zhuǎn)載本文請聯(lián)系愛笑的架構師公眾號。

一切的根源就是因為 HTTP 是一個無狀態(tài)的協(xié)議。
什么是無狀態(tài)呢?就是說這一次請求和上一次請求是沒有任何關系的,互不認識的,沒有關聯(lián)的。
看過電影《夏洛特煩惱》的小伙伴肯定記得夏洛和大爺?shù)囊欢螌υ挘?/p>
夏洛:大爺,樓上322住的是馬冬梅家嗎?
大爺:馬冬什么?
夏洛:馬冬梅。
大爺:什么冬梅啊?
夏洛:馬冬梅啊。
大爺:馬什么梅啊?
夏洛:……行,大爺,您先涼快吧。
「打岔」大爺記不住馬冬梅,就如同 HTTP 協(xié)議記不住上一次請求。說得通俗一點:HTTP 的記憶力不太好,需要借助『助聽器』。
記憶力不好的優(yōu)點就是一個字「快」;缺點也很明顯,需要借靠 cookie、session 、token等機制將客戶端多次請求關聯(lián)起來。
想象一下如果沒有 cookie、session、token 這樣的機制,我們在網(wǎng)站上每次點擊都需要重新輸入密碼認證,這樣槽糕的體驗你還愿意繼續(xù)用嗎?
在講解cookie、session 、token前我們先簡單講解兩個概念:認證、授權。
認證(Authentication)簡單來講就是驗證當前者的身份,證明你是你自己。
最常見的認證方式是通過用戶名和密碼,除此之外還有:
為了確認用戶的身份,防止請求偽造,在安全要求高的場合,經(jīng)常會使用組合認證(也叫多因素認證),也就是同時使用多個認證方式對用戶的身份進行校驗。
授權(Authorization)簡單來講就是授予第三方訪問用戶資源的權限。
在互聯(lián)網(wǎng)應用開發(fā)中,主要通過下面幾種方式實現(xiàn)授權:
cookie 的特點
設置 cookie
服務器向客戶端發(fā)送 Cookie 是通過 HTTP 響應報文實現(xiàn)的,在 Set-Cookie 中設置需要向客戶端發(fā)送的cookie,cookie格式如下:
- Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]
cookie 工作流程
(1)瀏覽器向服務器發(fā)送請求;
(2)服務器響應請求,向瀏覽器設置 cookie;
(3)瀏覽器將 cookie 存在本地,下一次請求帶上該 cookie;
(4)服務器響應請求。
cookie 常見屬性
(1)name=value
鍵值對,設置 Cookie 的名稱及相對應的值。
(2)domain
指定 cookie 所屬域名,默認是當前域名。如果 cookie 的 domain 設置為 taobao.com,那么 item.taobao.com, order.taobao.com 都是可以共享 cookie 的, 但是訪問 tmall.com 就不能共享 cookie 了,這就涉及跨域訪問的問題,跨域問題如何解決,這里不展開,有興趣可以自行搜索。
(3)path
指定 cookie 在哪個路徑(路由)下生效,默認是 '/'。如果設置為 /abc,則只有 /abc 下的路由可以訪問到該 cookie,如:/abc/read。
(4)expires
指定 cookie 的過期時間(GMT時間格式),到達該時間點后該 cookie 就會自動失效。
(5)max-age
HTTP 1.1中定義的,優(yōu)先級高于 expires 字段。
max-age 表示 cookie 有效期,單位秒。如果為正數(shù),則該 cookie 在 max-age 秒后失效;如果為負數(shù),該 cookie 為臨時 cookie ,關閉瀏覽器即失效,瀏覽器也不會以任何形式保存該 cookie ;如果為 0,表示刪除該 cookie 。默認為 -1。
(6)HttpOnly
如果給某個 cookie 設置了 httpOnly 屬性,則無法通過 JS 腳本讀寫該 cookie 的信息。
(7)secure
該 cookie 是否僅被使用安全協(xié)議傳輸,默認為false。當 secure 值為 true 時,cookie 在 HTTP 中是無效的。
session 翻譯過來就是『會話』。用戶打開一個瀏覽器, 點擊多個超鏈接, 訪問服務器多個web資源, 然后關閉瀏覽器, 整個過程稱之為一個會話。
(1)session 的特點
session 是另一種記錄服務器和客戶端會話狀態(tài)的機制;
session 存儲在服務器端,一般是文件中,也可以存在數(shù)據(jù)庫或緩存中。
session 一般基于 cookie 實現(xiàn)。session 中包含敏感信息存儲在服務器端,通常將 sessionId 存儲在客戶端的 cookie 中,客戶端每次請求攜帶 sessionId 即可識別用戶。
(2)session 工作流程
(1)用戶第一次請求,提交用戶名密碼等信息進行登錄認證,服務器根據(jù)用戶提交的信息進行鑒權,鑒權成功后創(chuàng)建 session 對象,并將 sessionId 塞入 cookie 中,瀏覽器收到響應信息將 cookie 存入本地;
(2)用戶第二次請求,以查看訂單信息為例,瀏覽器自動將當前域名下的 cookie 信息發(fā)送給服務端,服務端解析 cookie,獲取到 sessionId 后再查找對應的 session 對象,如果 session 對象存在說明用戶已經(jīng)登錄,繼續(xù)下一步操作。
從上面的流程可知,sessionId 是 cookie 和 session 中間的一道橋梁。
需要注意:如果客戶端禁用了 cookie,還可以通過 url 重寫等方法傳遞 sessionId。
(1)token 的組成
token 是驗證用戶身份的憑證,我們通常叫它:令牌。
最簡單的token組成: uid(用戶唯一的身份標識)、time(當前時間的時間戳)、sign(簽名,以哈希算法壓縮成一定長的十六進制字符串)
(2)token 特點
(3)token 工作流程
第一步:客戶端使用用戶名密碼或者掃碼等形式請求登錄;
第二步:服務端收到請求后進行鑒權,鑒權成功后服務端會生成一個 token 并發(fā)送給客戶端,客戶端收到 token 以后,會把它存儲起來,比如放在 cookie 里或者 localStorage 里;
第三步:客戶端下一次向服務端請求資源的時候需要帶著存儲的 token;
第四步:服務端收到請求,然后去驗證客戶端請求里面帶著的 token ,如果驗證成功,就向客戶端返回請求的數(shù)據(jù)。
需要注意:
(1)JWT 是標準 化的 token
從本質(zhì)上講 JWT 也是一種 token,只不過 JWT 是被大家廣泛接受的標準。
JWT 即:Json web token (JWT), 是為了在網(wǎng)絡應用環(huán)境間傳遞聲明而執(zhí)行的一種基于 JSON 的開放標準(RFC 7519)。
JWT的聲明一般被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便于從資源服務器獲取資源,也可以增加一些額外的其它業(yè)務邏輯所必須的聲明信息。
(2)JWT 的組成
JWT 共有三部分組成:
在https://jwt.io/網(wǎng)站上可以解析一個已知的 JWT:
jwt的頭部承載兩部分信息:聲明類型,這里是jwt;聲明加密的算法,通常直接使用 HMAC SHA256;
載荷就是存放有效信息的地方。主要包含三個部分:標準中注冊的聲明;公共的聲明;私有的聲明。
jwt 的第三部分是一個簽名信息,這個簽證信息由三部分組成:header (base64后的);payload (base64后的);secret。
(3)JWT 的特點
不在 jwt 的 payload 部分存放敏感信息,因為該部分是客戶端可解密的部分。
保護好 secret 私鑰,該私鑰非常重要。
如果可以,請使用 https 協(xié)議。
在分布式微服務技術日趨流行的今天,大型網(wǎng)站的設計都盡量避免使用 session 實現(xiàn) HTTP 狀態(tài)化。
session簡單粗暴,在服務端維護會話信息,在客戶端保存session id,服務端能夠輕易地把會話控制在自己的手中,但服務集群化產(chǎn)生了session共享的負擔;
jwt(token)只在客戶端保存會話信息,服務端通過密鑰校驗會話,(相比session)拿時間換空間,卸下了服務端集群共享會話信息的負擔,同時也加大了服務端控制會話的難度。