正文開始之前,我們先要瞭解一個概念,就是什麼是 登錄態。 主流Web應用比如瀏覽器是基於http協議的,而http協議是 無狀態 的。什麼是 無狀態?就是伺服器不知道是誰發送了這個http請求,無法識別區分用戶身份。 所以登錄態就是服務端用來區分用戶身份,同時對用戶進行記錄的技術方案。 ...
正文開始之前,我們先要瞭解一個概念,就是什麼是 登錄態
。
主流Web應用比如瀏覽器是基於http協議的,而http協議是 無狀態
的。什麼是 無狀態
?就是伺服器不知道是誰發送了這個http請求,無法識別區分用戶身份。
所以登錄態就是服務端用來區分用戶身份,同時對用戶進行記錄的技術方案。
那怎麼實現用戶的登錄態呢?常見的實現流程如下:
- 客戶端用戶輸入登錄憑據(如賬戶和密碼),發送登錄請求。
- 服務端校驗用戶是否合法(如認證和鑒權),合法後返回登錄態,不合法返回第1步。
- 合法後攜帶登錄態訪問用戶數據。
流程有了,如何實現呢?
常見的方案有HTTP基本認證、Cookie和Session認證、Token認證、單點登錄認證等,下麵一一介紹。
1. HTTP基本認證
HTTP基本認證是HTTP協議本身提供了一種服務端對客戶端進行用戶身份驗證的方法。 流程如下:
sequenceDiagram
autonumber
客戶端->>服務端:Get / HTTP/1.1 Host:www.qq.com
服務端->>客戶端:HTTP/1.1 401 Unauthorised WWW-Authenticate: Basic realm="qq.com"
客戶端->>客戶端:彈出登錄視窗
客戶端->>服務端:Get / HTTP/1.1 Host:www.qq.com Authorization: Basic xxxxxx
服務端->>客戶端:驗證成功,返回用戶數據
- 客戶端向服務端請求需要登錄態的數據
- 服務端向客戶端返回401狀態碼,要求客戶端驗證
- 客戶端根據返回的
WWW-Authenticate: Basic realm="qq.com"
,彈出用戶名和密碼輸入框要求用戶進行驗證。 - 用戶輸入用戶名和密碼後,客戶端將用戶名及密碼以
Base64
格式發送給服務端。 - 服務端驗證通過後返回用戶數據。
這是一種比較簡單的驗證用戶身份的方式,甚至不需要寫代碼,只要後端伺服器配置一下即可。
優點:相容性好,主流瀏覽器都支持
缺點:
- 不安全,賬號密碼是Base64編碼,很容易解碼。
- 無法主動註銷,除非關閉標簽或瀏覽器。
2. Cookie和Session認證
先瞭解兩個概念,Cookie和Session是什麼呢? 上面說到HTTP是一種無狀態協議
,而Cookie和Session可以彌補 HTTP 的無狀態特性。
2.1 什麼是Cookie
Cookie是客戶端請求服務端時,由服務端創建並由客戶端存儲和管理的小文本文件。具體流程如下:
- 客戶端首次發起請求。
- 服務端通過HTTP響應頭裡Set-Cookie欄位返回Cookie信息。
- 客戶端再發起請求時會通過HTTP請求頭裡Cookie欄位攜帶Cookie信息。
2.2 什麼是Session
Session是客戶端請求服務端時服務端會為這次請求創建一個數據結構,這個結構可以通過記憶體、文件、資料庫等方式保存。具體流程如下:
- 客戶端首次發起請求。
- 服務端收到請求並自動為該客戶端創建特定的Session並返回SessionID,用來標識該客戶端。
- 客戶端通過服務端響應獲取SessionID,併在後續請求攜帶SessionID。
- 服務端根據收到的SessionID,在服務端找對應的Session,進而獲取到客戶端信息。
2.3 Cookie和Session認證流程
- 客戶端向服務端發送認證信息(例如賬號密碼)
- 服務端根據客戶端提供的認證信息執行驗證邏輯,如果驗證成功則生成Session並保存,同時通過響應頭Set-Cookie欄位返回對應的SessionID
- 客戶端再次請求併在Cookie里攜帶SessionID。
- 服務端根據SessionID查找對應的Session,並根據業務邏輯返回相應的數據。
2.4 Cookie和Session認證優點
- Cookie由客戶端管理,支持設定有效期、安全加密、防篡改、請求路徑等屬性。
- Session由服務端管理,支持有效期,可以存儲各類數據。
2.4 Cookie和Session認證缺點
- Cookie只能存儲字元串,有大小和數量限制,對移動APP端支持不好,同時有跨域限制(主域不同)。
- Session存儲在服務端,對服務端有性能開銷,客戶端量太大會影響性能。如果集中存儲(如存儲在Redis),會帶來額外的部署維護成本。
3. Token認證
Token又叫令牌,是服務端生成用來驗證客戶端身份的憑證,客戶端每次請求都攜帶Token。 Token一般由以下數據組成:
uid(用戶唯一的身份標識)
time(當前時間的時間戳)
sign(簽名,由token的前幾位+鹽用哈希演算法壓縮成一定長的十六進位字元串)
3.1 Token認證流程
- 客戶端向服務端發送認證信息(例如賬號密碼)
- 服務端根據客戶端提供的認證信息執行驗證邏輯(如查詢資料庫),如果驗證成功則生成Token並返回。
- 客戶端存儲(可以存在Cookie、LocalStorage或本地緩存里)收到的Token,再次請求時攜帶Token(可以通過HTTP請求頭Authorization欄位)。
- 服務端校驗Token(如查詢資料庫),並根據業務邏輯返回相應的數據。
3.2 Token認證優點
- 客戶端可以用Cookie、LocalStorage等存儲,服務端不需要存儲。
- 安全性高(有簽名校驗)。
- 支持移動APP端。
- 支持跨域。
3.3 Token認證缺點
- 占用額外傳輸寬頻,因為Token比較大,可能會消耗一定的流量。
- 每次簽名校驗會消耗服務端性能。
- 有效期短(避免被盜用)。
3.4 Refresh Token
3.3里說到為了避免被盜用Token一般有效期比較短。但是有效期太短會造成客戶端不斷重新登錄,體驗太差。有沒有什麼辦法可以解決這個問題呢?
那就是再來一個Token,一個專門生成Token的Token,稱為 Refresh Token
。
流程如下:
- 客戶端向服務端發送認證信息(例如賬號密碼)
- 服務端根據客戶端提供的認證信息執行驗證邏輯(如查詢資料庫),如果驗證成功則生成Token和Refresh Token並返回。
- 客戶端存儲(可以存在Cookie、LocalStorage或本地緩存里)收到的Token和Refresh Token,再次請求時攜帶Token(可以通過HTTP請求頭Authorization欄位)。
- 服務端校驗Token(如查詢資料庫),並根據業務邏輯返回相應的數據。
- 服務端發現Token過期了,拒絕了請求。
- 客戶端重新請求並攜帶Refresh Token。
- 服務端校驗Refresh Token並返回新Token和新Refresh Token。
- 客戶端再次請求並攜帶新Token。
3.5 JWT
3.3、3.4里服務端校驗客戶端發過來的Token是否有效時,可能會查詢資料庫來驗證。如果每次請求都要查詢資料庫,可能會帶來額外性能消耗。
那這個有沒有辦法優化呢?
答案是有的,那就是JWT(JSON Web Token
)。JWT
是 Auth0
提出的通過 對JSON進行加密簽名
來實現授權驗證的方案。
JWT也是一種Token,由三部分組成: Header頭部
、 Payload負載
和 Signature簽名
。它是一個很長的字元串,中間用點( .
)分隔成三個部分,列如 :
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Header頭部:
{ "alg": "Hash演算法(HMAC、SHA256或RSA)", "typ": "Token的類型(JWT)" }
Payload負載:
{ "iss": "簽發人(issuer)", "exp": "過期時間(expiration time)", "sub": "主題(subject)", "aud": "受眾(audience)", "nbf": "生效時間(not before)", "iat": "簽發時間(issued at)", "jti": "編號(JWT ID)", "uid": "自定義欄位(可以存儲用戶ID等)", }
Signature 簽名:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret //設置的密鑰 )
JWT的流程和Token的基本一樣,因為已經攜帶了客戶端信息(如用戶ID等),所以服務端校驗Token時不需要查詢資料庫了。
4. 單點登錄認證
上面說的都是同一個功能變數名稱(或同一主域)下,通過Cookie或Token攜帶憑證實現登錄態管理。但是如果有很多功能變數名稱,如何實現用戶在一個功能變數名稱下登錄後,訪問另一個功能變數名稱也能自動登錄呢?
這就是單點登錄問題(Single Sign On
)
要實現SSO,需要有一個CAS(Central Authentication Service)
中央授權服務(假設功能變數名稱為cas.com)來提供統一的登錄功能。
假如現在有功能變數名稱http://abc.com和http://123.com要實現互相自動登錄。流程如下:
- 客戶端訪問http://abc.com
- http://abc.com發現沒有登錄(http://abc.com域下沒有Session或Session失效),302跳轉到http://cas.com並攜帶http://abc.com的回調地址(登錄成功跳轉回來的頁面鏈接)。
- http://cas.com發現沒有登錄(http://cas.com域下沒有Session或Session失效),302跳轉到http://cas.com登錄頁面並攜帶http://abc.com的回調地址。
- 客戶端攜帶http://abc.com回調地址訪問http://cas.com。
- 客戶端向http://cas.com發送認證信息(例如賬號密碼)。
- http://cas.com登錄成功並生成http://cas.com域下的Session,同時生成一個Token,根據回調地址攜帶此Token重定向到http://abc.com。
- 客戶端攜帶Token訪問http://abc.com。
- http://abc.com訪問http://cas.com驗證Token的有效性,驗證成功並生成http://abc.com域下的Session,完成登錄。
- 客戶端訪問http://123.com
- http://123.com校驗失敗,需要登錄(http://123.com域下沒有Session或Session失效),302重定向到http://cas.com,並攜帶http://123.com回調地址。
- 客戶端攜帶http://123.com回調地址訪問http://cas.com。
- http://cas.com根據http://cas.com下的Session(訪問http://abc.com時生成的)發現用戶已登錄,生成Token後302重定向到http://123.com。
- http://123.com訪問http://cas.com驗證Token的有效性,驗證成功並生成http://123.com域下的Session,完成登錄。
總結:
- HTTP基本認證:一般用於對安全要求不高或內部系統用戶量極少的場景,實際應用不多。
- Cookie和Session認證:一般應用於瀏覽器環境。
- Token認證:除了瀏覽器環境外,還可以應用於移動端APP、小程式、PC端軟體等非瀏覽器環境。
- 單點登錄認證:應用於大型站群系統或企業內不同業務系統間互通。
以上總結4種了常見的登錄方案,還有OAuth2.0、掃碼登錄等方式,後續還會繼續更新,敬請期待。。。
作者:yanweiyao
本文來自博客園,作者:古道輕風,轉載請註明原文鏈接:https://www.cnblogs.com/88223100/p/One-article-to-understand-the-common-login-schemes-of-the-front-and-rear-end.html