Inspired by :
一文教你搞定所有前端鑒權與后端鑒權方案,讓你不再迷惘 - 掘金 (juejin.cn)

Terminology
-
認證(Identification) :根據宣告者所特有的識別資訊,確認宣告者的身份,
身份證,用戶名和密碼等 -
授權(Authorization): 在資訊安全領域是指資源所有者委派執行者,賦予執行者指定范圍的資源操作權限,以便對資源的相關操作,
現實生活領域: 銀行卡(由銀行派發)、門禁卡(由物業管理處派發)、鑰匙(由房東派發)
互聯網領域: web 服務器的 session 機制、web 瀏覽器的 cookie 機制、頒發授權令牌(token)等 -
鑒權(Authentication): 在資訊安全領域是指對于一個宣告者所宣告的身份權利,對其所宣告的真實性進行鑒別確認的程序,授權和鑒權是兩個上下游相匹配的關系,先授權,后鑒權,
現實生活領域: 門禁卡需要通過門禁卡識別器,銀行卡需要通過銀行卡識別器;
互聯網領域: 校驗 session/cookie/token 的合法性和有效性 -
權限控制(Access/Permission Control): 將可執行的操作定義為權限串列,然后判斷操作是否允許/禁止
對于權限控制,可以分為兩部分進行理解:一個是權限,另一個是控制,權限是抽象的邏輯概念,而控制是具體的實作方式,
現實生活領域: 門禁卡的權限
互聯網領域: 通過 web 后端服務,控制介面訪問,允許或拒絕訪問請求
關系
前后依次發生

使用門禁卡開門: 認證、授權、鑒權、權限控制四個環節一氣呵成,在瞬間同時發生
用戶的網站登錄: 用戶在使用用戶名和密碼進行登錄時,認證和授權兩個環節一同完成,而鑒權和權限控制則發生在后續的請求訪問中,比如在選購物品或支付時,
1.HTTP基本鑒權
在 HTTP 中,基本認證方案(Basic Access Authentication) 是允許客戶端(通常指的就是網頁瀏覽器)在請求時,通過用戶提供用戶名和密碼的方式,實作對用戶身份的驗證,
幾乎所有網站都不會使用此認證方案

缺點
- 不安全
- 無法主動注銷
2. Session-Cookie 鑒權
Session-Cookie 認證是利用服務端的 Session和 客戶端 的 Cookie 來實作的前后端通信認證模式,
Cookie
HTTP 無狀態(對于事務處理沒有記憶能力,每次客戶端和服務端會話完成時,服務端不會保存任何會話資訊)
為了讓服務器區分不同的客戶端,服務端就必須主動的去維護一個狀態,這個狀態用于告知服務端前后兩個請求是否來自同一瀏覽器,而這個狀態可以通過 Cookie 去實作,
特點:
- 存盤在客戶端,可隨意篡改,不安全
- 有大小限制,最大為 4kb
- 有數量限制,一般一個瀏覽器對于一個網站只能存不超過 20 個 Cookie,瀏覽器一般只允許存放 300個 Cookie
- Android 和 IOS 對 Cookie 支持性不好
- 不可跨域
Session
無狀態協議通信程序中,為了實作中斷/繼續操作,將用戶和服務器之間的互動進行的一種抽象;
具體來說,是服務器生成的一種具有特定結構的資料,可以通過多種方式保存,如記憶體、資料庫、檔案等,大型網站一般有專門的 Session 服務器集群來保存用戶會話
原理流程:
- 客戶端: 用戶向服務器首次發送請求;
- 服務器: 接收到資料并自動為該用戶創建特定的 Session / Session ID,來標識用戶并跟蹤用戶當前的會話程序;
- 客戶端: 瀏覽器收到回應獲取會話資訊,并且會在下一次請求時帶上 Session / Session ID;
- 服務器: 服務器提取后會與本地保存的 Session ID進行對比找到該特定用戶的會話,進而獲取會話狀態;
- 至此客戶端與服務器的通信變成有狀態的通信;
特點:
- Session 保存在服務器上;
- 通過服務器自帶的加密協議進行;
與 Cookie 的差異:
- 安全性: Cookie 由于保存在客戶端,可隨意篡改,Session 則不同存盤在服務器端,無法偽造,所以 Session 的安全性更高;
- 存取值的型別不同: Cookie 只支持字串資料,Session 可以存任意資料型別;
- 有效期不同: Cookie 可設定為長時間保持,Session 一般失效時間較短;
- 存盤大小不同: Cookie 保存的資料不能超過 4K;
Session-Cookie:將Session存盤在客戶端的Cookie中

Pros
- Cookie 簡單易用
- Session 資料存盤在服務端,相較于 JWT 方便進行管理,也就是當用戶登錄和主動注銷,只需要添加洗掉對應的 Session 就可以了,方便管理
- 只需要后端操作即可,前端可以無感等進行操作
Cons
- 依賴 Cookie(用戶可能在瀏覽器端禁用 Cookie)
- 非常不安全,Cookie 將資料暴露在瀏覽器中,增加了資料被盜的風險(容易被 CSRF 等攻擊)
- Session 存盤在服務端(Redis),增大了服務端的開銷,用戶量大的時候會大大降低服務器性能
- 對移動端的支持性不友好
前端常用庫
- 使用 express:express-session
- 使用 koa:koa-session
3. Token 鑒權
避免Session-Cookie 缺點
Token
Token 是一個令牌,客戶端訪問服務器時,驗證通過后服務端會為其簽發一張令牌,之后,客戶端就可以攜帶令牌訪問服務器,服務端只需要驗證令牌的有效性即可,
即:訪問資源介面(API)時所需要的資源憑證
一般 Token 的組成:uid (用戶唯一的身份標識) + time (當前時間的時間戳) + sign (簽名,Token 的前幾位以哈希演算法壓縮成的一定長度的十六進制字串)

Pros
- 服務端無狀態化、可擴展性好: Token 機制在服務端不需要存盤會話(Session)資訊,因為 Token 自身包含了其所標識用戶的相關資訊,這有利于在多個服務間共享用戶狀態
- 支持 APP 移動端設備;
- 安全性好: 有效避免 CSRF 攻擊(因為不需要 Cookie)
- 支持跨程式呼叫: 因為 Cookie 是不允許跨域訪問的,而 Token 則不存在這個問題
Cons
- 配合: 需要前后端配合處理;
- 占帶寬: 正常情況下比
sid更大,消耗更多流量,擠占更多寬帶 - 性能問題: 雖說驗證 Token 時不用再去訪問資料庫或遠程服務進行權限校驗,但是需要對 Token 加解密等操作,所以會更耗性能;
- 有效期短: 為了避免 Token 被盜用,一般 Token 的有效期會設定的較短,需要
Refresh Token
Refresh Token
業務介面用來鑒權的 Token,稱為 Access Token,
為了安全, Access Token 有效期一般設定較短,以避免被盜用,但過短的有效期會造成 Access Token 經常過期
解決辦法:
- 重繪
Access Token,讓用戶重新登錄獲取新 Token,會很麻煩; - 引入一個專門生成 Access Token 的 Token,稱為
Refresh Token
區別
- Access Token: 用來訪問業務介面,由于有效期足夠短,盜用風險小,也可以使請求方式更寬松靈活;
- Refresh Token: 用來獲取 Access Token,有效期可以長一些,通過獨立服務和嚴格的請求方式增加安全性;由于不常驗證,也可以如前面的 Session 一樣處理;

與 Session-Cookie 的區別
Session-Cookie 和 Token 有很多類似的地方, Token 像是 Session-Cookie 的升級改良版,存在以下區別
- 存盤地不同: Session 一般是存盤在服務端;Token 是無狀態的,一般由前端存盤;
- 安全性不同: Session 和 Token 并不矛盾,作為身份認證 Token 安全性比 Session 好,因為每一個請求都有簽名還能防止監聽以及重放攻擊;
- 支持性不同: Session-Cookie 認證需要靠瀏覽器的 Cookie 機制實作,如果遇到原生 NativeAPP 時這種機制就不起作用了,或是瀏覽器的 Cookie 存盤功能被禁用,也是無法使用該認證機制實作鑒權的;而 Token 驗證機制豐富了客戶端型別,
如果用戶資料可能需要和第三方共享,或者允許第三方呼叫 API 介面,則應使用 Token
4. JWT(JSON Web Token)鑒權
服務端驗證客戶端發送過來的 Token 時,還需要查詢資料庫獲取用戶基本資訊,然后驗證 Token 是否有效
每次請求驗證都要查詢資料庫,增加了查庫帶來的延遲等性能消耗;
**業界常用解決方案: JWT **
JWT
JWT 是 Auth0 提出的通過 對 JSON 進行加密簽名來實作授權驗證的方案
就是登錄成功后將相關用戶資訊組成 JSON 物件,然后對這個物件進行某種方式的加密,回傳給客戶端; 客戶端在下次請求時帶上這個 Token; 服務端再收到請求時校驗 token 合法性,其實也就是在校驗請求的合法性,
組成
它是一個很長的字串,中間用點(.)分隔成三個部分
-
Header通常包括兩部分
- typ:代表 Token 的型別,這里使用的是 JWT 型別;
- alg:使用的 Hash 演算法,例如 HMAC SHA256 或 RSA.
-
Payload包含一些宣告 Claim (物體的描述,通常是一個 User 資訊,還包括一些其他的元資料) ,用來存放實際需要傳遞的資料
JWT 規定了7個官方欄位:
- iss (issuer):簽發人
- exp (expiration time):過期時間
- sub (subject):主題
- aud (audience):受眾
- nbf (Not Before):生效時間
- iat (Issued At):簽發時間
- jti (JWT ID):編號
除了官方欄位,還可以在這個部分定義私有欄位
-
SignatureSignature 部分是對前兩部分的簽名,防止資料篡改,
首先,需要指定一個密鑰(secret),這個密鑰只有服務器才知道,不能泄露給用戶,然后,使用 Header 里面指定的簽名演算法(默認是 HMAC SHA256)產生簽名,
使用方式
客戶端收到服務器回傳的 JWT,可以儲存在 Cookie 里面,也可以儲存在 localStorage,
此后,客戶端每次與服務器通信,都要帶上這個 JWT,
可以把它放在 Cookie 里面自動發送,但是這樣不能跨域,所以更好的做法是放在 HTTP 請求的頭資訊Authorization欄位里面,
Authorization: Bearer <token>

Pros
- 不需要在服務端保存會話資訊(RESTful API 的原則之一就是無狀態),所以易于應用的擴展,即資訊不保存在服務端,不會存在 Session 擴展不方便的情況
- JWT 中的 Payload 負載可以存盤常用資訊,用于資訊交換,有效地使用 JWT,可以降低服務端查詢資料庫的次數
Cons
- 加密問題: JWT 默認是不加密,但也是可以加密的,生成原始 Token 以后,可以用密鑰再加密一次,
- 到期問題: 由于服務器不保存 Session 狀態,因此無法在使用程序中廢止某個 Token,或者更改 Token 的權限,也就是說,一旦 JWT 簽發了,在到期之前就會始終有效,除非服務器部署額外的邏輯,
前端常用庫
- 使用 express:express-jwt
- 使用 koa:koa-jwt
5. 單點登錄(Single Sign On)
避免大型系統內子系統的重復登錄,只需要登錄一次,就可以訪問其他相互信任的應用系統
例如
- 登錄天貓,淘寶也會自動登錄;
- 登錄百度貼吧,百度網盤也會自動登錄;
同域SSO
當百度網站存在兩個相同主域名下的貼吧子系統 tieba.baidu.com 和網盤子系統 pan.baidu.com 時,以下為他們實作 SSO 的步驟:
- 客戶端: 用戶訪問某個子系統時(例如
tieba.baidu.com),如果沒有登錄,則跳轉至 SSO 認證中心提供的登錄頁面進行登錄; - 服務端: 登錄認證后,服務端把登錄用戶的資訊存盤于 Session 中,并且附加在回應頭的
Set-Cookie欄位中,設定 Cookie 的 Domain 為.baidu.com; - 客戶端:再次發送請求時,攜帶主域名 Domain 下的 Cookie 給服務器,此時服務端就可以通過該 Cookie 來驗證登錄狀態了;
亦即 Session-Cookie 認證
異域SSO
如天貓 (tmall.com) 和 淘寶 (taobao.com)
利用 CAS(Central Authentication Service)中央授權服務

-
客戶端: 開始訪問系統 A;
-
系統 A: 發現用戶未登錄,重定向至 CAS 認證服務(sso.com),同時 URL 地址引數攜帶登錄成功后回跳到系統 A 的頁面鏈接(sso.com/login?redir…
-
CAS 認證服務: 發現請求 Cookie 中沒有攜帶登錄的票據憑證(TGC),所以 CAS 認證服務判定用戶處于
未登錄狀態,重定向用戶頁面至 CAS 的登錄界面,用戶在 CAS 的登錄頁面上進行登錄操作, -
客戶端: 輸入用戶名密碼進行 CAS 系統認證;
-
CAS 認證服務: 校驗用戶資訊,并且
生成 TGC放入自己的 Session 中,同時以 Set-Cookie 形式寫入 Domain 為sso.com的域下 ;同時生成一個授權令牌 ST (Service Ticket),然后重定向至系統 A 的地址,重定向的地址中包含生成的 ST(重定向地址:www.taobao.com?token=ST-345678) -
系統 A: 拿著 ST 向 CAS 認證服務發送請求,CAS 認證服務驗證票據 (ST) 的有效性,驗證成功后,系統 A 知道用戶已經在 CAS 登錄了(其中的 ST 可以保存到 Cookie 或者本地中),系統 A 服務器使用該票據 (ST) 創建與用戶的會話,稱為區域會話,回傳受保護資源;
-
客戶端: 開始訪問系統 B;
-
系統 B: 發現用戶未登錄,重定向至 SSO 認證服務,并將自己的地址作為引數傳遞,并附上在 sso.com 域下的 cookie 值是第五步生成的 TGC;
-
CAS 認證服務: CAS 認證服務中心發現用戶已登錄,跳轉回系統 B 的地址,并附上票據 (ST) ;
-
系統 B: 拿到票據 (ST),去 CAS 認證服務驗證票據 (ST) 的有效性,驗證成功后,客戶端也可以跟系統 B 交往了 ~
注意
- 如圖中流程所示,我們發現
CAS 認證服務在簽發的授權令牌 ST后,直接重定向,這樣其實是比較容易容易被竊取,那么我們需要在系統 A 或者系統 B 在向 CAS 驗證成功 (如圖中的第 14 步和第 11 步) 后,再生成另一個新的驗證 Token 回傳給客戶端保存; - CAS 一般提供四個介面:
/login:登錄介面,用于登錄到中央授權服務/logout:登出介面,用于從中央授權服務中登出/validate:用于驗證用戶是否登錄中央授權服務/serviceValidate:用于讓各個 Service 驗證用戶是否登錄中央授權服務
- CAS 生成的票據:
- TGT(Ticket Grangting Ticket) :TGT 是 CAS 為用戶簽發的
登錄票據,擁有了 TGT,用戶就可以證明自己在 CAS 成功登錄過, - TGC:Ticket Granting Cookie: CAS Server 生成TGT放入自己的 Session 中,而 TGC 就是這個 Session 的唯一標識(SessionId),以 Cookie 形式放到瀏覽器端,是 CAS Server 用來明確用戶身份的憑證,
- ST(Service Ticket) :ST 是 CAS 為用戶簽發的訪問某個 Service 的票據,
- TGT(Ticket Grangting Ticket) :TGT 是 CAS 為用戶簽發的
6. OAuth 2.0
是一種授權機制,資料的所有者告訴系統,同意授權第三方應用進入系統,獲取這些資料,系統從而產生一個短期的進入令牌(Token),用來代替密碼,供第三方應用使用,
令牌與密碼的差異:
令牌(Token) 與 密碼(Password) 的作用是一樣的,都可以進入系統,但是有三點差異,
- 令牌是短期的,到期會自動失效: 用戶自己無法修改,密碼一般長期有效,用戶不修改,就不會發生變化,
- 令牌可以被資料所有者撤銷,會立即失效,
- 令牌有權限范圍(scope): 對于網路服務來說,只讀令牌就比讀寫令牌更安全,密碼一般是完整權限,
OAuth 2.0 對于如何頒發令牌的細節,規定得非常詳細,具體來說,一共分成四種授權模式 (Authorization Grant) ,適用于不同的互聯網場景,
無論哪個模式都擁有三個必要角色:客戶端、授權服務器、資源服務器,有的還有用戶(資源擁有者),
授權碼模式(Authorization Code Grant)
授權碼(Authorization Code Grant) 方式,指的是第三方應用先申請一個授權碼,然后再用該碼獲取令牌,
這種方式是最常用的流程,安全性也最高,它適用于那些有后端服務的 Web 應用,授權碼通過前端傳送,令牌則是儲存在后端,而且所有與資源服務器的通信都在后端完成,這樣的前后端分離,可以避免令牌泄漏,


隱藏式模式(Implicit Grant)
有些 Web 應用是純前端應用,沒有后端,這時就不能用上面的方式了,必須將令牌儲存在前端,OAuth2.0 就規定了第二種方式,允許直接向前端頒發令牌,這種方式沒有授權碼這個中間步驟,所以稱為(授權碼)"隱藏式"(implicit),

用戶名密碼式模式(Password Credentials Grant)
如果你高度信任某個應用,OAuth 2.0 也允許用戶把用戶名和密碼,直接告訴該應用,該應用就使用你的密碼,申請令牌,這種方式稱為"密碼式"(password)
客戶端模式(Client Credentials Grant)
客戶端模式指客戶端以自己的名義,而不是以用戶的名義,向授權服務器 進行認證,
主要適用于沒有前端的命令列應用,
選型


7. 聯合登錄和信任登錄
聯合登錄
指同時包含多種憑證校驗的登錄服務,同時,也可以理解為使用第三方憑證進行校驗的登錄服務,
example: 對于兩個網站 A 和 B,在登錄 A 網站的時候用 B 網站的帳號密碼,或者登錄 B 網站的時候使用 A 網站的帳號密碼
這樣的概念其實與上面所講的 OAuth2.0 的 用戶名密碼式模式 認證方式類似,
最經典的莫過于 APP 內嵌 H5 的使用場景,當用戶從 APP 進入內嵌的 H5 時,我們希望 APP 內已登錄的用戶能夠訪問到 H5 內受限的資源,而未登錄的用戶則需要登錄后訪問,
這里思路主要有兩種,一種是原生跳轉內嵌 H5 頁面時,將登錄態 Token 附加在 URL 引數上,另一種則是內嵌 H5 主動通過與原生客戶端制定的協議獲取應用內的登錄狀態,
信任登錄
指所有不需要用戶主動參與的登錄,例如建立在私有設備與用戶之間的系結關系,憑證就是私有設備的資訊,此時不需要用戶再提供額外的憑證,信任登錄又指用第三方比較成熟的用戶庫來校驗憑證,并登錄當前訪問的網站,
example: 在 A 網站有登錄狀態的時候,可以直接跳轉到 B 網站而不用登錄,就是 信任登錄,
目前比較常見的第三方信任登錄帳號如:QQ 號淘寶帳號、支付寶帳號、微博帳號等,
不難發現 OAtuth 2.0 其實就是信任登錄的縮影,因為正是有了OAuth,我們的信任登錄才得以實作,
8. 唯一登錄
實作用戶只能在一個設備上登錄,禁止用戶重復登錄

9. 掃碼登錄
無需在網頁上輸入任何賬號和密碼,只需要讓移動端 APP (如微信、淘寶、QQ等等) 中已登錄用戶主動掃描 二維碼 ,再確認登錄,以使 PC 端的同款應用得以快速登錄,需要三端 (PC端、手機端、服務端) 來進行配合才能達到登錄成功的效果
二維碼
二維碼 又稱二維條碼,常見的二維碼為 QR Code,QR 全稱 Quick Response,是一個近幾年來移動設備上超流行的一種編碼方式,它比傳統的Bar Code條形碼能存更多的資訊,也能表示更多的資料型別,

10. 一鍵登錄(適用于原生APP)
傳統賬號密碼登錄缺點
- 要求用戶要記住自己的賬號和密碼,存在記憶成本,用戶為了降低記憶成本,很可能會在不同平臺使用同一套賬號密碼,從安全角度考慮,一旦某個平臺的賬號密碼泄露了,會連累到該用戶使用的其他平臺,
- 賬號和個人身份無關,意味著同一個用戶可以注冊多個不同的賬號,可能出現惡意注冊情況,
隨著無線互聯的發展以及手機卡實名制的推廣,手機號儼然已成為特別的身份證明,與賬號密碼相比,手機號可以更好地驗證用戶的身份,防止惡意注冊,
但是手機號注冊還是需要一系列繁瑣的操作:輸入手機號、等待短信驗證碼、輸入驗證碼、點擊登錄,整個流程少說二十秒,而且如果收不到短信,也就登錄補了,這類問題有可能導致潛在的用戶流失,
從安全角度考慮,還存在驗證碼泄漏的風險,如果有人知道了你的手機號,并且竊取到了驗證碼,那他也能登錄你的賬號了,
一鍵登錄,
直接獲取到當前手機使用的手機卡號進行登錄
取決于運營商是否開放相關服務;隨著運營商開放了相關的服務,我們現在已經能夠接入運營商提供的 SDK 并付費使用相關的服務

三大運營商開放平臺:
- 移動 - 互聯網能力開放平臺
- 電信 - 天翼賬號開放平臺
- 聯通 - WO+ 開放平臺
由于國內三大運營商各自有獨立的 SDK,所以會導致兼容方面的作業會特別繁瑣,如果要采用一鍵登錄的方案,不妨采用第三方提供了號碼認證服務,下列幾家供應商都擁有手機號碼認證能力:
- 阿里 - 號碼認證服務
- 創藍 - 閃驗
- 極光 - 極光認證
- mob - 秒驗
注意:
在認證程序中,需要用戶打開蜂窩網路,如果手機設備沒有插入 SIM 卡、或者關閉蜂窩網路的情況下,是無法完成認證的,所以就算接入一鍵登錄,還是要兼容傳統的登錄方式,允許用戶在失敗的情況下,仍能正常完成登錄流程,
總結
HTTP 基本認證適用于內部網路,或者對安全要求不是很高的網路;
Session-Cookie 適用于一般中大型的網站(移動端 APP 除外);
Token 和 JWT 都適用于市面上大部分的企業型網站,JWT 效能會優于 Token;
單點登錄 適用于子系統較多的大型企業網站;
OAuth 2.0適用于需要快速注冊用戶型的網站;
掃碼登錄 適用于已完成部署了三端的企業;
一鍵登錄 適用于原生 APP;
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/531832.html
標籤:其他
上一篇:達芬奇DaVinci Resolve Studio 18 for mac/win(視頻調色軟體)中文最新
下一篇:電商營銷總結
