正文開始之前,我們先要了解一個概念,就是什么是 登錄態,
主流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://123.com

先訪問http://abc.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校驗失敗,需要登錄(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
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/540407.html
標籤:其他
