基于session會話的登錄認證機制
該機制的核心在于服務器session和客戶端sessionId的交互。用戶登錄完成后,服務器會構建用戶會話session,會話內包含了用戶標志及登錄狀態,并向瀏覽器返回sessoinId。之后用戶在做其他接口請求時,將sessionId攜帶上。服務器檢索到會話session并進行登錄鑒權判斷。
整個機制是十分簡單明了的,但在設計細節上,還是由很多發揮的空間。我們先看一看session會話登錄認證機制的基本流程
認證過程大致如下:
- 用戶輸入用戶名、密碼或者用短信驗證碼方式登錄系統;
- 服務端驗證后,創建一個 Session 信息,并且將 SessionID 存到 cookie,發送回瀏覽器;
- 下次客戶端再發起請求,自動帶上 cookie 信息,服務端通過 cookie 獲取 Session 信息進行校驗;
問題點:
會話信息直接存儲在什么地方? 對于用戶量少的非分布式web系統,可以直接使用代碼框架的session能力。反之,則需要一套緩存服務(redis)在多臺web服務器之間共享session會話。
cookie 存在 CSRF(跨站請求偽造)的風險。sessionId的cookie屬性設置為httpOnly和secure,保證cookie值不能被前端js代碼讀取到;通過校驗reffer header是否合法,防止非自有web系統發起的請求;通過使用https協議,防止黑客冒充合法的web系統。
用戶會話保持和失效——用戶登出則服務器session清除。用戶長時間不操作用戶狀態失效(設定緩存時間),用戶持續發起請求則用戶狀態保持登錄(會話快過期時刷新失效時間),瀏覽器關閉重開是否保持會話可通過cookie屬性設置。
sessionId理論上還能放置在什么地方?除了放置在cookie里,理論上還可以放置在header中,body中,url路徑中。放header中是可行的,但一般是在app應用里。對于web應用,還需把sessionId先存儲在localstorage,那樣才能在新開瀏覽器tab時讀取重新放置到header中。放在body里理論上可以,但對于服務端的鑒權會更麻煩。放在url里則是不安全的,可通過csrf被黑客截取到。
基于token鑒權的登錄認證機制
token鑒權是一種直接把用戶的登錄憑證直接存到客戶端的方案。在用戶登錄驗證成功之后,將登錄憑證做數字簽名和加密之為token返回給客戶端。用戶在做其他接口請求時,將token攜帶上。服務器將該token解密驗簽判斷其有效性。
整個機制的關鍵在于token的生成和驗證
問題:
經過簽名加密后,token字符串會很長,但里面有效信息占比較小,同時也影響性能。 盡量減少token里的信息量,最簡單的形式可以只包含用戶id,憑證創建時間和過期時間三個值。
token如何保證每次登錄的安全隨機? 如上,添加上時間戳可以保證每次登錄的token值都不一樣。
用戶會話保持和失效——用戶登出則清理客戶端token,用戶長時間不操作用戶狀態失效(token中含緩存時間),用戶持續發起請求則用戶狀態保持登錄(每次請求刷新token返回),瀏覽器關閉重開是否保持會話token保存位置決定。
token放置的位置??梢苑旁赾ookie中,CSRF風險同會話管理。每次請求都可以無感刷新token。對于app客戶端。放在header上,則可能存儲在localstorage或sessionStorage里,其生命周期影響了會話保持。
兩類登錄認證機制的對比
這兩種登錄認證機制差異還是蠻大的。
從原理層面上看,session會話機制中,服務器為你保管了登錄憑證,然后給了客戶端一個信物。客戶端帶著信物訪問,服務器能根據這個信息找到登錄憑證就是有效的;token認證機制中,服務器將登錄憑證打上記號鎖在盒子里再給到客戶端。客戶端帶著這個上鎖的盒子訪問,服務器拿出他的鎖打開并檢查記號,都對上了則說明登錄憑證可以使用。當然,登錄憑證里也有失效
從效果層面上看,session會話機制中,服務器需要自己騰出空間保存憑證和記錄,而token認證機制中,服務器則只需保管好鑰匙,信息本身是保存在客戶端。因此,session會話需要更多存儲空間;token認證機制需要額外的token解析時間,本身不存儲任何用戶的登錄狀態
但有時候,又不是那么絕對。例如token鑒權中,對于強業務的web系統,后端web服務必然也還會再關聯個session會話做業務邏輯的處理;對于要求用戶單端登錄的情況,如果同時異地登錄,舊的token要求被踢下,此時后端web服務就得存儲用戶token及ip或設備等信息。具體的設計原則,還是得看系統的業務屬性。畢竟,一個系統,可不會僅包含用戶登錄鑒權。
附:初始登錄鑒權
自有賬號體系登錄
略
三方賬號 Oauth2.0 登錄流程
流程示意圖:
[圖片上傳失敗...(image-a55a38-1609677363093)]
- 用戶選擇華為帳號登錄,開發者應用發起授權碼Code請求。
- 華為帳號服務器呈現授權頁面給用戶,用戶確認授權。
- 華為帳號服務器通過開發者應用配置的回調地址,返回授權碼Code。(
- 開發者應用發起Code換Token請求。
- 華為帳號服務器返回憑證(Access Token)、用戶信息(ID Token)。
- 之后用上一步獲取的 access_token 去請求華為賬號服務器獲取用戶的基本信息,例如頭像、昵稱等;
- 保存到用戶憑證中,完成登錄。
自有系統 SSO單點登錄
流程示意圖:
- 用戶向后臺業務系統發起請求時,先驗證局部登錄會話是否創建。如果未創建,則先跳轉到SSO單點登錄系統進行登錄操作.
- SSO認證中心引導用戶登錄,完成登錄驗證
- 驗證OK,則生成ticket.并將User對象轉化為JSON數據,創建全局會話。(這里基于cookie-session的機制)
- 攜帶ticket跳轉回業務系統的前臺頁面 (當業務系統與SSO認證中心同域的情況下,ticket可直接放在域名cookie下)
- 用戶重新在瀏覽器頁面發起了操作
- 業務系統后臺向SSO認證中心驗證ticket合法性,以獲取用戶登錄憑證。并在自己的服務域名下創建局部會話。
以上兩個流程實際上大同小異,都遵循外部鑒權系統的兩個核心步驟————鑒權認證中心(外部賬號系統、自有SSO認證中心)在登錄完成后頒發令牌,業務系統拿著該令牌向鑒權認證中心請求驗證。 前一步可以通過cookie或url參數的性質通過前端傳到業務系統,該令牌被泄露了也無關緊要;第二步則由后臺服務向鑒權中心發起認證,這里則需要服務之間的互信。oauth機制中,可以通過appid和secret來保證互信。SSO認證中心則可以通過秘鑰管理的方式來保證互信。