1、Cookie
指某些網站為了辨別使用者身份而儲存在使用者本地終端(Client Side)上的資料(通常經過加密)。
HTTP是一種無狀態傳輸協議,它不能以狀態來區分和管理請求和響應。也就是說,伺服器單從網路連線上無從知道客戶身份。於是給客戶端釋出一個通行證—cookie來區分,這就是Cookie的工作原理。
伺服器通過response的set-cookie告訴客戶端去寫入cookie,後面的請求都會攜帶該cookie。
cookie有以下重要引數:
2、Session
session 是另一種記錄伺服器和客戶端會話狀態的機制。session儲存在伺服器端,該會話對應的key即sessionId會被儲存到客戶端的cookie中。
根據以上流程可知,session通過cookie來傳遞sessionId,達到使用者鑑權的目的。除此之外,sessionId也可以不通過cookie傳遞,比如通過response返回客戶端,再當作請求的引數傳遞給伺服器去驗證。
Cookie 和 Session 對比
- 安全性: Session 比 Cookie 安全,Session 是儲存在伺服器端的,Cookie 是儲存在客戶端的。
- 存取值的型別:Cookie只支援存字串資料,想要設定其他型別的資料,需要將其轉換成字串,Session 可以存任意資料型別。
- 有效期: Cookie可設定為長時間保持,比如我們經常使用的預設登入功能,Session 一般失效時間較短,客戶端關閉(預設情況下)或者 Session 超時都會失效。
- 儲存大小: 單個 Cookie 儲存的資料不能超過 4K,Session 可儲存資料遠高於 Cookie,但是當訪問量過多,會佔用過多的伺服器資源。
session缺點:
- 佔資源: 每個經過認證的使用者都要存放session到記憶體中,而隨著認證使用者的增多,服務端的開銷較大。
- CSRF攻擊:基於cookie來進行使用者識別時,使用者cookie如果被截獲,就容易受到跨站請求偽造的攻擊。
3、Token
token(令牌) 是一串字串,通常作為鑑權憑據,最常用的使用場景是 API 鑑權。
一般來說 token 主要有三種:
- 自定義的 token:開發者根據業務邏輯自定義的 token
- JWT:JSON Web Token,定義在 RFC 7519 中的一種 token 規範
- Oauth2.0:定義在 RFC 6750 中的一種授權規範,其實並不是一種 token,只是其中也有用到 token。
token特點:
- 服務端無狀態化、可擴充套件性好
- 支援移動端裝置
- 安全性高
- 支援跨程式呼叫
token鑑權流程:
Refresh Token
refresh token 是專用於重新整理 access token 的 token。Access Token的有效期比較 短,當 Acesss Token 由於過期而失效時,使用 Refresh Token 就可以獲取到新的 Token,如果 Refresh Token過期就只能重新登陸了。
Token 和 Session 的區別
- Session 是一種記錄伺服器和客戶端會話狀態的機制,使服務端有狀態化,可以記錄會話資訊。而 Token 是令牌,訪問資源介面(API)時所需要的資源憑證。Token 使服務端無狀態化,不會儲存會話資訊。
- Session 和 Token 並不矛盾,作為身份認證 Token 安全性比 Session 好,因為每一個請求都有簽名還能防止監聽以及
- 重放攻擊
- ,而 Session 就必須依賴鏈路層來保障通訊安全了。如果你需要實現有狀態的會話,仍然可以增加 Session 來在伺服器端儲存一些狀態。
- 所謂 Session 認證只是簡單的把 User 資訊儲存到 Session 裡,因為 SessionID 的不可預測性,暫且認為是安全的。而 Token ,如果指的是 OAuth Token 或類似的機制的話,提供的是 認證 和 授權 ,認證是針對使用者,授權是針對 App 。其目的是讓某 App 有權利訪問某使用者的資訊。
4、JWT
JSON Web Token(簡稱JWT)是目前最流行的跨域認證解決方案,是一種認證授權機制,是一種基於 JSON 的開放標準。
JWT組成
一個 JWT token 是一個字串,它由頭部、載荷與簽名三部分組成,中間用 . 分隔,形式如下:
base64(header).base64(json payload).signature
複製程式碼
詳細介紹參見:阮一峰JSON Web Token 入門教程
JWT 認證流程:
- 使用者輸入使用者名稱/密碼登入,服務端認證成功後,會返回給客戶端一個 JWT。
- 客戶端將 jwt 儲存到本地,當使用者希望訪問一個受保護的路由或者資源的時候,需要請求頭的 Authorization 欄位中使用 Bearer 模式新增 JWT 。
- 服務端的保護路由將會檢查請求頭 Authorization 中的 JWT 資訊,如果合法,則允許訪問。因為 JWT 內部包含了一些使用者資訊,因此減少了需要查詢資料庫的需要。
JWT 的使用方式
1、存放在cookie中
當使用者希望訪問一個受保護的路由或者資源的時候,可以把它放在 Cookie 裡面自動傳送,但是這樣不能跨域。
2、存放在localstorage中,新增到header中傳送
請求時放在 HTTP 請求頭資訊的 Authorization 欄位裡,使用 Bearer 模式新增 JWT。
Authorization: Bearer <token>
複製程式碼
3、通過介面引數
可以把 JWT 放在 POST 請求的資料體裡,或者通過 URL 的 queryString 傳輸。
自定義Token 和 JWT 的關係
相同點: 都是訪問資源的令牌,都可以記錄使用者的資訊,都是使服務端無狀態化,都是隻有驗證成功後,客戶端才能訪問服務端上受保護的資源
區別:服務端驗證客戶端發來的token資訊要進行資料的查詢操作;JWT驗證客戶端發來的token資訊就不用, 在服務端使用金鑰校驗就可以,不用資料庫的查詢。
5、各種鑑權方式注意點
使用 cookie 注意點
- 因為儲存在客戶端,容易被客戶端篡改,使用前需要驗證合法性
- 不要儲存敏感資料,比如使用者密碼,賬戶餘額
- 使用 httpOnly 在一定程度上提高安全性
- 儘量減少 cookie 的體積,能儲存的資料量不能超過 4kb
- 設定正確的 domain 和 path,減少資料傳輸
- cookie 無法跨域,子域名可以訪問父域名
- 一個瀏覽器針對一個網站最多存 20 個Cookie,瀏覽器一般只允許存放 300 個Cookie
- 移動端對 cookie 的支援不是很好,而 session 一般基於 cookie 實現,所以移動端常用的是 token
使用 session 注意點
- 使用者同時線上量較多時,session 儲存在伺服器會佔據較多記憶體,需要定期清理過期 的 session
- 當網站採用叢集部署的時候,會遇到多臺 web 伺服器之間如何做 session 共享的問題。因為 session是由單個伺服器建立的,處理使用者請求的伺服器不一定是 那個建立 session 的伺服器,那麼該伺服器就無法拿到之前已經放入到 session 中的登入憑證之類的資訊了。
- 當多個應用要共享 session時,因為不同的應用可能部署的主機不一樣需要在各個應用做好 cookie 跨域的處理。
- sessionId 是儲存在 cookie 中的,假如瀏覽器禁止 cookie 或不支援 cookie ,一般會把 sessionId 跟在 url 引數後面即重寫 url,所以 session 不一定非得需要靠 cookie 實現
使用 token 注意點
- 如果你認為用資料庫來儲存 token會導致查詢時間太長,可以選擇放在 記憶體當中,比如 redis 很適合你對 token 查詢的需求。
- token 完全由應用管理,所以它可以避開同源策略
- token 可以避免 CSRF 攻擊(因為不需要 cookie 了)
- 移動端對 cookie 的支援不是很好,而 session 需要基於 cookie 實現,所以移動端常用的是 token
使用 JWT 時需要考慮的問題
- JWT 預設是不加密,但也是可以加密的。生成原始 Token 以後,可以用金鑰再加密一次。
- JWT 不加密的情況下,不能將祕密資料寫入 JWT。
- JWT 不僅可以用於認證,也可以用於交換資訊。有效使用 JWT,可以降低伺服器查詢資料庫的次數。
- JWT 最大的優勢是伺服器不再需要儲存Session,使得伺服器認證鑑權業務可以方便擴充套件。但這也是 JWT 最大的缺點:由於伺服器不需要儲存 Session 狀態,因此使用過程中無法廢棄某個 Token 或者更改 Token 的許可權。也就是說一旦 JWT 簽發了,到期之前就會始終有效,除非伺服器部署額外的邏輯。
- JWT 本身包含了認證資訊,一旦洩露,任何人都可以獲得該令牌的所有許可權。為了減少盜用,JWT的有效期應該設定得比較短。對於一些比較重要的許可權,使用時應該再次對使用者進行認證。
- JWT 適合一次性的命令認證,頒發一個有效期極短的JWT,即使暴露了危險也很小由 於每次操作都會生成新的 JWT,因此也沒必要儲存 JWT,真正實現無狀態。
- 為了減少盜用,JWT 不應該使用 HTTP 協議明碼傳輸,要使用 HTTPS 協議傳輸。