HTTP協議是無狀態的,每次HTTP請求響應后,就會斷開這次連接。如果客戶端再次發送請求,服務端也不能識別出這個客戶端是不是上次請求過的客戶端,HTTP協議不能進行會話跟蹤。而Cookie,Session,Token正是為了解決HTTP協議無狀態問題。
Cookie
Cookie機制是在客戶端實現,采用客戶端保持狀態的方案。
Cookie由服務端生成,發送給客戶端(Set-Cookie),客戶端請求的時候會帶上這個Cookie。
請求流程:
Cookie字段:名字、值、過期時間、路徑和域。路徑與域一起構成Cookie的作用范圍。
通過Chrome的開發者工具中看到,在github.com上保存在客戶端的Cookie信息。
- Name:名字
- Value:值
- Domain:域
- Path:路徑
- Expaires/Max-Age:過期時間
上圖中logged_in
和user_session
兩個Cookie值表示登錄github.com后保存下來的登錄狀態和Session。
Session
Session是在服務端實現,當客戶端請求服務端時,服務端會檢查請求中是否包含Session標識(Session id),
- 如果沒有,那么服務端就生成一個隨機的Session以及和它匹配的Session id,并將Session id返回給客戶端。
- 如果有,那么服務器就在存儲中根據Session id 查找到對應的Session。
Token
Token也稱作令牌,由uid+time+sign[+固定參數]組成:
- uid:用戶唯一身份標識
- time:當前時間的時間戳
- sign:簽名, 使用 hash/encrypt 壓縮成定長的十六進制字符串,可以防止惡意第三方拼接Token請求服務器
以下幾點特性會讓你在程序中使用基于Token的身份驗證:
- 無狀態、可擴展
- 支持移動設備
- 跨程序調用
- 安全
Token是有客戶端來保存,用戶的狀態在服務端的內存中是不存儲的,所以這是一種無狀態的認證機制。而認證的具體流程如下:
客戶端使用用戶名跟密碼請求登錄
服務端收到請求,去驗證用戶名與密碼
驗證成功后,服務端會簽發一個 Token,再把這個 Token 發送給客戶端
客戶端收到 Token 以后可以把它存儲起來,比如放在 Cookie 里或者 Local Storage 里
客戶端每次向服務端請求資源的時候需要帶著服務端簽發的 Token
服務端收到請求,然后去驗證客戶端請求里面帶著的 Token,如果驗證成功,就向客戶端返回請求的數據
第三方授權登錄
這是Token的一種應用場景,使用OAuth實現。
OAuth(開放授權)是一個開放標準,允許用戶讓第三方應用訪問該用戶在某一網站上存儲的私密的資源(如照片,視頻,聯系人列表),而無需將用戶名和密碼提供給第三方應用。
OAuth允許用戶提供一個令牌,而不是用戶名和密碼來訪問他們存放在特定服務提供者的數據。
我們看下github的授權流程:
區別
Cookie和Session
維度 | Cookie | Sesson |
---|---|---|
存放位置 | 客戶端 | 服務端 |
存取方式 | 只能保管ASCII字符串 | 任何類型的數據 |
安全性 | 對客戶端是可見的, 客戶端的一些程序可能會窺探、 復制以至修正Cookie中的內容 |
對客戶端是透明的, 不存在敏感信息泄露的風險 |
有效期 | 可以保持很長時間不過期 | 依賴于JSESSIONID的Cookie, 默許過期時間為–1, 只需關閉了瀏覽器,該Session就會失效 |
跨域支持 | 支持跨域名訪問 | 僅在它所在的域名內有效 |
Token和Session
作為身份認證Token安全性比Session好。
Session是一種HTTP存儲機制,目的是為無狀態的HTTP提供的持久機制。
Token,如果指的是OAuth Token 或類似的機制的話,提供的是認證
和授權
,認證是針對用戶,授權是針對App。