首頁  >  文章  >  【總結分享】10種常用前後端鑑權方法,讓你不再迷惘

【總結分享】10種常用前後端鑑權方法,讓你不再迷惘

青灯夜游
青灯夜游轉載
2022-08-23 19:27:548373瀏覽

關於前端鑑權這塊,Token、Cookie、Session、JWT、單一登入、掃碼登入、一鍵登入是什麼意思?分別有什麼作用?你一般是怎麼做的?以及你是怎麼儲存的呢?那你又是怎麼保證它的安全的呢?以下這篇文章教你搞定前後端所有鑑權方案,讓你不再迷惘!

還記得之前在面試的時候,有一位面試官就問了,關於前端鑑權這塊,Token、Cookie、Session、JWT、單點登入是什麼?有什麼作用?你一般是怎麼做的?以及你是怎麼儲存的呢?那你又是怎麼保證 的安全的呢?

一頓連問下來,我是焦頭又爛額,欲言而又止.......

其實鑑權的方法有很多,下面我總結了常用的10種鑑權方法,那麼哪一種是最適合你的系統呢?哪一種又最安全呢?

那就讓我們從下文慢慢探索尋找答案 ~

透過這篇文章你將學到什麼?

【總結分享】10種常用前後端鑑權方法,讓你不再迷惘

在介紹鑑權方法之前,我們先要了解的是:什麼是認證、授權、鑑權、權限控制以及他們之間的關係,有了他們做鋪墊,那麼我們才能做到從頭到尾的了解透徹~

什麼是認證?

認證(Identification) 是指根據宣告者所特有的識別訊息,確認宣告者的身分。

白話文的意思是:你需要用身分證證明你自己是你自己

例如我們常見的認證技術:

  • 身分證
  • 使用者名稱和密碼
  • 使用者手機:手機簡訊、手機二維碼掃描、手勢密碼
  • 使用者的電子郵件信箱
  • 使用者的生物學特徵:指紋、語音、眼睛虹膜
  • 使用者的大數據辨識
  • 等等

什麼是授權?

授權(Authorization): 在資訊安全領域是指資源擁有者委派執行者,賦予執行者指定範圍的資源操作權限,以便對資源的相關操作。

在現實生活領域例如: 銀行卡(由銀行發放)、門禁卡(由物業管理處派發)、鑰匙(由房東派發),這些都是現實生活中授權的實現方式。

在網際網路領域例如: web 伺服器的 session 機制、web 瀏覽器的 cookie 機制、頒發授權令牌(token)等都是一個授權的機制。

什麼是鑑權?

鑑權(Authentication) 在資訊安全領域是指對於一個宣告者所宣告的身分權利,對其所宣告的真實性進行鑑別確認的過程

若從授權出發,則會更容易理解鑑權。授權和鑑權是兩個上下游相符的關係,先授權,後鑑權

在現實生活領域: 門禁卡需要通過門禁卡識別器,銀行卡需要通過銀行卡識別器;

##在互聯網領域: 校驗session/cookie/token 的合法性和有效性

鑑權 是一個承上啟動的一個環節,上游它接受授權的輸出,校驗其真實性後,然後取得權限(permission),這個將會為下一步的權限控製做好準備。

什麼是權限控制?

權限控制(Access/Permission Control) 將可執行的操作定義為權限列表,然後判斷操作是否允許/禁止

對於權限控制,可以分為兩部分來理解:一個是權限,一個是控制。權限是抽象的邏輯概念,而控制是具體的實作方式。

在現實生活領域中: 以門禁卡的權限實現為例,一個門禁卡,擁有開公司所有的門的權限;一個門禁卡,擁有管理員角色的權限,因而可以開公司所有的門。

在互聯網領域: 透過 web 後端服務,來控制介面訪問,允許或拒絕存取請求。

認證、授權、鑑權和權限控制的關係?

看到這裡,我們應該明白了

認證授權鑑權權限控制#這四個環節是一個前後依序發生上下游的關係;

【總結分享】10種常用前後端鑑權方法,讓你不再迷惘

需要說明的是,這四個環節在有些時候會同時發生。例如在下面的幾個場景:

  • 使用門禁卡開門: 認證、授權、鑑權、權限控制四個環節一氣呵成,在瞬間同時發生
  • 使用者的網站登入: 使用者在使用使用者名稱和密碼登入時,認證和授權兩個環節一同完成,而鑑權和權限控制則發生在後續的請求存取中,例如在選購物品或付款時。

這裡提個小問題,供大家思考:認證和鑑權之間的關係?歡迎大家在留言區討論

既然我們已經了解了他們之間的關係,那麼我們應該好好講講關於前端鑑權有哪些?以及他們之間存在的差異點又在哪裡呢?

1. HTTP 基本鑑權


在HTTP 中,基本認證方案(Basic Access Authentication) 是允許客戶端(通常指的就是網頁瀏覽器)在請求時,透過使用者提供使用者名稱和密碼的方式,實現使用者身分的驗證。

因為幾乎所有的線上網站都不會走該認證方案,所以該方案大家了解即可

1.1認證流程圖

【總結分享】10種常用前後端鑑權方法,讓你不再迷惘

#1.2 認證步驟解析

  • 客戶端(如瀏覽器): 向伺服器請求一個受限的清單資料或資源,例如欄位如下

     GET /list/ HTTP/1.1
     Host: www.baidu.com
     Authorization: Basic aHR0cHdhdGNoOmY=
  • 伺服器:客戶端你好,這個資源在安全區baidu.com

    裡,是受限資源,需要基本認證;

    並且向客戶端回傳401狀態碼(Unauthorized 未被授權的)以及附帶提供了一個認證域

    www-Authenticate: Basic realm=”baidu.com”要求進行身份驗證;

    其中
  • Basic
  •  就是驗證的模式,而 

    realm="baidu.com" 則表示客戶端需要輸入這個安全域的使用者名稱和密碼,而不是其他網域的

     HTTP/1.1 401 Unauthorized
     www-Authenticate: Basic realm= "baidu.com"
  • 客戶端:
伺服器,我已經攜帶了使用者名稱和密碼給你了,你看一下;(註:如客戶端是瀏覽器,那麼此時會自動彈出一個彈窗,讓使用者輸入使用者名稱及密碼);

輸入使用者名稱及密碼後,則客戶端將使用者名稱及密碼以Base64 加密方式傳送至伺服器傳送的格式如下(其中Basic 內容為:使用者名稱:密碼 的ase64 形式

):

 GET /list/ HTTP/1.1 
 Authorization: Basic Ksid2FuZzp3YW5n==

伺服器: 客戶端你好,我已經校驗了 Authorization

欄位你的使用者名稱和密碼,是正確的,這是你要的資源。
     HTTP/1.1 200 OK
     ...
  • 1.3 優點
    • 很簡單,基本上所有流行的瀏覽器都支援
  • 1.4 缺點

    • # 不安全:
  • 由於是基於HTTP 傳輸,所以它在網路上幾乎是裸奔的,雖然它使用了Base64 來編碼,但這個編碼很容易就可以解碼出來。 即使認證內容無法被解碼為原始的使用者名稱和密碼也是不安全的,惡意使用者可以再取得了認證內容後使用其不斷的享伺服器發起請求,這就是所謂的重播攻擊。

    無法主動登出


    #由於HTTP 協定沒有提供機制清除瀏覽器中的Basic 認證訊息,除非標籤頁或瀏覽器關閉、或使用者清除歷史記錄。


    1.5 使用場景

    #內部網絡,或對安全要求不是很高的網路。

    2. Session-Cookie 識別碼

    Session-Cookie 認證是利用服務端的Session(會話)和瀏覽器(客戶端) 的Cookie 來實現的前後端通訊認證模式。

    在理解這句話之前我們先簡單了解下 什麼是 Cookie

    以及

    什麼是 Session

    ######2.1 什麼是Cookie#############眾所周知,###HTTP 是無狀態的協定###(對於交易處理沒有記憶能力,每次客戶端和服務端會話完成時,服務端不會保存任何會話資訊);######所以為了讓伺服器區分不同的客戶端,就必須主動的去維護一個狀態,這個狀態用於告知服務端前後兩個請求是否來自同一瀏覽器。而這個狀態可以透過 ###Cookie### 去實現。 #########特點:#######
    • Cookie 儲存在客戶端,可隨意篡改,不安全
    • 有大小限制,最大為4kb
    • 有數量限制,一般一個瀏覽器對於一個網站只能存不超過20 個Cookie,瀏覽器一般只允許存放300個Cookie
    • Android 和IOS 對Cookie 支援性不好
    • Cookie 是不可跨域的,但是一級網域和二級網域是允許共享使用的(靠的是domain)

    2.2 什麼是Session

    Session 的抽象概念是會話,在無狀態協定通訊過程中,為了實現中斷/繼續操作,將使用者和伺服器之間的互動進行的一種抽象;

    具體來說,是伺服器產生的一種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 中呢? Bingo

    ,的確是這樣的,我們接著往下看

    2.3 Session-Cookie 的認證流程圖

    【總結分享】10種常用前後端鑑權方法,讓你不再迷惘

    2.4 Session-Cookie 認證步驟解析

      客戶端:
    • 向伺服器發送登入資訊使用者名稱/密碼來要求登入校驗;

    • 伺服器:
    • 驗證登入的訊息,驗證通過後來自動建立Session(將Session 儲存在記憶體中,也可以儲存在Redis 中),然後給這個Session 產生一個唯一的識別字串會話身分憑證 

      session_id(通常稱為 sid),並在回應頭 Set-Cookie 中設定這個唯一識別碼;註:可以使用簽章對

      sid
      進行加密處理,服務端會根據對應的

      secret 金鑰進行解密(非必須步驟)

    • 客戶端:
    • 收到伺服器的回應後會解析回應頭,並自動將 

      sid 儲存在本機Cookie 中,瀏覽器在下次HTTP 請求時請求頭會自動附帶上該網域下的Cookie 資訊;

    • 伺服器:
    • 接收客戶端請求時會去解析請求頭Cookie 中的 

      sid,然後根據這個 sid 去找服務端保存的該客戶端的 sid,然後判斷該請求是否合法;

    2.5 Session-Cookie 的優點

    #Cookie 簡單易用

      Session 資料儲存在服務端,相較於JWT 方便進行管理,也就是當使用者登入和主動註銷,只需要新增刪除對應的Session 就可以了,方便管理
    • 只需要後端操作即可,前端可以無感等進行操作;
    2.6 Session-Cookie 的缺點

    • 依賴Cookie,一旦使用者在瀏覽器端停用Cookie,那麼就GG 思密達了;
    • 非常不安全,Cookie 將資料暴露在瀏覽器中,增加了資料被盜的風險(容易被CSRF 等攻擊);
    • Session 儲存在服務端,增大了服務端的開銷,用戶量大的時候會大大降低伺服器效能;
    • 對行動端的支持性不友善;

    2.7 使用場景

    • #一般中大型的網站都適用(除了APP 行動端) ;
    • 由於一般的Session 需集中儲存在記憶體伺服器上(如Redis),這樣就會增加伺服器的預算,所以預算不夠請謹慎選擇;

    2.8 前端常用的Session 函式庫推薦

    3. Token 鑑權


    #現在我們已經得知,Session-Cookie 的一些缺點,以及Session 的維護對服務端造成很大困擾,我們必須找地方存放它,又要考慮分散式的問題,甚至要單獨為了它啟用一套Redis 叢集。那有沒有更好的辦法?

    Token 就應運而生了

    3.1 什麼是Token(令牌)

    Token

    是一個令牌,客戶端存取伺服器時,驗證透過後服務端會為其簽發一張令牌,之後,客戶端就可以攜帶令牌存取伺服器,服務端只需要驗證令牌的有效性即可。

    一句話概括;存取資源介面(API)時所需要的資源憑證

    【總結分享】10種常用前後端鑑權方法,讓你不再迷惘

    一般Token 的組成:

    uid
      (使用者唯一的身分識別)
    • time

      (目前時間的時間戳記) sign (簽名,Token 的前幾位被雜湊演算法壓縮成的一定長度的十六進位字串)

    • Token 的認證流程圖:

    • Token 認證步驟解析:

    • 客戶端: 輸入使用者名稱和密碼請求登入校驗;

    • ##伺服器:

      收到請求,去驗證使用者名稱與密碼;驗證成功後,服務端會簽發一個Token 並把這個Token 傳送給客戶端;

    客戶端:

    收到Token 以後需要把它儲存起來,web 端通常會放在localStorage 或Cookie 中,行動端原生APP 一般儲存在本機快取中;

    • 客戶端發送請求: 向服務端請求API 資源的時候,將Token 透過HTTP 請求頭Authorization 欄位或其它方式傳送給服務端;
    • 伺服器:
    • 收到請求,然後去驗證客戶端請求裡面帶著的Token ,如果驗證成功,就向客戶端返回請求的數據,否則拒絕返還(401);
    • ##Token 的優點:
    服務端無狀態化、可擴充性好:

    Token 機制在服務端不需要儲存會話( Session)訊息,因為Token 本身包含了其所標識使用者的相關訊息,這有利於在多個服務間共享使用者狀態##支援APP 行動端裝置;

    • 安全性好: 有效避免CSRF 攻擊(因為不需要Cookie)
    • 支援跨程式呼叫: 因為Cookie 是不允許跨網域存取的,而Token 則不存在這個問題
    • Token 的缺點:
    • # 配合: 需要前後端配合處理;
    • 佔頻寬:
    正常情況下比 

    sid 更大,消耗更多流量,擠佔更多寬頻效能問題:

    雖然驗證Token 時不用再去存取資料庫或遠端服務進行權限校驗,但需要對Token 加解密等操作,所以會更耗效能;

    有效期限短:

    為了避免Token 被盜用,一般Token 的有效期會設定的較短,所以就有了

    Refresh Token;

    3.2 什麼是Refresh Token(刷新Token )

    ###業務介面用來鑑權的Token,我們稱之為###Access Token###。 ######為了安全,我們的 ###Access Token### 有效期限一般設定較短,以避免被盜用。但過短的有效期會造成 ###Access Token### 經常過期,過期後怎麼辦呢? ######一種方法是:###刷新 Access Token###,讓使用者重新登入取得新 Token,會很麻煩;###

    另外一种办法是:再来一个 Token,一个专门生成 Access Token 的 Token,我们称为 Refresh Token

    • Access Token: 用来访问业务接口,由于有效期足够短,盗用风险小,也可以使请求方式更宽松灵活;
    • Refresh Token: 用来获取 Access Token,有效期可以长一些,通过独立服务和严格的请求方式增加安全性;由于不常验证,也可以如前面的 Session 一样处理;

    Refresh Token 的认证流程图:

    【總結分享】10種常用前後端鑑權方法,讓你不再迷惘

    Refresh Token 认证步骤解析:

    • 客户端: 输入用户名和密码请求登录校验;

    • 服务端: 收到请求,验证用户名与密码;验证成功后,服务端会签发一个 Access TokenRefresh Token 并返回给客户端;

    • 客户端:Access TokenRefresh Token 存储在本地;

    • 客户端发送请求: 请求数据时,携带 Access Token 传输给服务端;

    • 服务端:

      • 验证 Access Token 有效:正常返回数据
      • 验证 Access Token 过期:拒绝请求
    • 客户端 ( Access Token 已过期) 则重新传输 Refresh Token 给服务端;

    • 服务端 ( Access Token 已过期) 验证 Refresh Token ,验证成功后返回新的 Access Token 给客户端;

    • 客户端: 重新携带新的 Access Token 请求接口;

    3.3 Token 和 Session-Cookie 的区别

    Session-CookieToken 有很多类似的地方,但是 Token 更像是 Session-Cookie 的升级改良版。

    • 存储地不同: Session 一般是存储在服务端;Token 是无状态的,一般由前端存储;
    • 安全性不同: Session 和 Token 并不矛盾,作为身份认证 Token 安全性比 Session 好,因为每一个请求都有签名还能防止监听以及重放攻击;
    • 支持性不同: Session-Cookie 认证需要靠浏览器的 Cookie 机制实现,如果遇到原生 NativeAPP 时这种机制就不起作用了,或是浏览器的 Cookie 存储功能被禁用,也是无法使用该认证机制实现鉴权的;而 Token 验证机制丰富了客户端类型。

    如果你的用户数据可能需要和第三方共享,或者允许第三方调用 API 接口,用 Token 。如果永远只是自己的网站,自己的 App,用什么就无所谓了。

    4. JWT(JSON Web Token)鉴权


    通过第三节,我们知道了 Token 的使用方式以及组成,我们不难发现,服务端验证客户端发送过来的 Token 时,还需要查询数据库获取用户基本信息,然后验证 Token 是否有效;

    这样每次请求验证都要查询数据库,增加了查库带来的延迟等性能消耗;

    那么这时候业界常用的 JWT 就应运而生了!!!

    4.1 什么是 JWT

    JWTAuth0 提出的通过 对 JSON 进行加密签名来实现授权验证的方案;

    就是登录成功后将相关用户信息组成 JSON 对象,然后对这个对象进行某种方式的加密,返回给客户端; 客户端在下次请求时带上这个 Token; 服务端再收到请求时校验 token 合法性,其实也就是在校验请求的合法性。

    4.2 JWT 的组成

    JWT 由三部分组成: Header 头部Payload 负载Signature 签名

    它是一个很长的字符串,中间用点(.)分隔成三个部分。列如 :

     eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

    Header 头部:

    在 Header 中通常包含了两部分:

    • typ:代表 Token 的类型,这里使用的是 JWT 类型;
    • alg:使用的 Hash 算法,例如 HMAC SHA256 或 RSA.
     {
       "alg": "HS256",
       "typ": "JWT"
     }

    Payload 负载:

    它包含一些声明 Claim (实体的描述,通常是一个 User 信息,还包括一些其他的元数据) ,用来存放实际需要传递的数据,JWT 规定了7个官方字段:

    • iss (issuer):签发人
    • exp (expiration time):过期时间
    • sub (subject):主题
    • aud (audience):受众
    • nbf (Not Before):生效时间
    • iat (Issued At):签发时间
    • jti (JWT ID):编号

    除了官方字段,你还可以在这个部分定义私有字段,下面就是一个例子。

     {
       "sub": "1234567890",
       "name": "John Doe",
       "admin": true
     }

    Signature 签名

    Signature 部分是对前两部分的签名,防止数据篡改。

    首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。

     HMACSHA256(
       base64UrlEncode(header) + "." +
       base64UrlEncode(payload),
       secret)

    4.3 JWT 的使用方式

    客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。

    此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息Authorization字段里面。

     Authorization: Bearer <token></token>

    4.4 JWT 的认证流程图

    其实 JWT 的认证流程与 Token 的认证流程差不多,只是不需要再单独去查询数据库查找用户用户;简要概括如下:

    【總結分享】10種常用前後端鑑權方法,讓你不再迷惘

    4.5 JWT 的优点

    • 不需要在服务端保存会话信息(RESTful API 的原则之一就是无状态),所以易于应用的扩展,即信息不保存在服务端,不会存在 Session 扩展不方便的情况;
    • JWT 中的 Payload 负载可以存储常用信息,用于信息交换,有效地使用 JWT,可以降低服务端查询数据库的次数

    4.6 JWT 的缺点

    • 加密问题: JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。
    • 到期问题: 由于服务器不保存 Session 状态,因此无法在使用过程中废止某个 Token,或者更改 Token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。

    4.7 前端常用的 JWT 库推荐

    5. 单点登录(Single Sign On)


    前面我们已经知道了,在同域下的客户端/服务端认证系统中,通过客户端携带凭证,可以维持一段时间内的登录状态。

    但随着企业的发展,一个大型系统里可能包含 n 多子系统,用户在操作不同的系统时,需要多次登录,很麻烦,那么单点登录(SSO) 就可以很好的解决这个问题的,在多个应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统。

    • 例如登录天猫,淘宝也会自动登录;
    • 登录百度贴吧,百度网盘也会自动登录;

    5.1 同域下的 SSO(主域名相同)

    当百度网站存在两个相同主域名下的贴吧子系统 tieba.baidu.com 和网盘子系统 pan.baidu.com 时,以下为他们实现 SSO 的步骤:

    • 客户端: 用户访问某个子系统时(例如 tieba.baidu.com),如果没有登录,则跳转至 SSO 认证中心提供的登录页面进行登录;

    • 服务端: 登录认证后,服务端把登录用户的信息存储于 Session 中,并且附加在响应头的 Set-Cookie 字段中,设置 Cookie 的 Domain 为 .baidu.com

    • 客户端:再次发送请求时,携带主域名 Domain 下的 Cookie 给服务器,此时服务端就可以通过该 Cookie 来验证登录状态了;

    其实我们不难发现,这就是我们上面讲的 Session-Cookie 认证 登录方式; 但如果是不同域呢?毕竟不同域之间 Cookie 是不共享的,那怎么办?

    5.2 跨域下的 SSO(主域名不同)

    在我們常見的購物網站天貓(tmall.com) 和淘寶(taobao.com) 中,我們只需要登錄其中某一個系統,另外一個系統打開後就會默認登錄,那麼這是怎麼做的呢?

    那麼就有了CAS(Central Authentication Service)中央授權服務,那麼我們先主要說下CAS 的流程;

    單一登入下的CAS 認證流程圖:

    【總結分享】10種常用前後端鑑權方法,讓你不再迷惘

    #單一登入下的CAS 認證步驟詳解:

    • 客戶端: 開始存取系統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) 建立與使用者的會話,稱為局部會話,返回受保護資源;

    到這裡客戶端就可以跟系統A 愉快的交往啦~

      到這裡客戶端就可以跟系統A 愉快的交往啦~
    • #客戶端:
    • 開始存取系統B;

    • #系統B:
    • 發現使用者未登錄,重新導向至SSO 認證服務,並將自己的位址作為參數傳遞,並附上在sso.com 網域下的cookie 值是第五步驟產生的TGC;

    • CAS 認證服務:
    • CAS 認證服務中心發現使用者已登錄,跳到系統B 的位址,並附上票據(ST) ;

    • 系統B:
    拿到票據(ST),去CAS 認證服務驗證票據(ST) 的有效性。驗證成功後,客戶端也可以跟系統B 交往了~

    (PS:腳踏兩艘船,感覺有點渣呀~)

      #單一登入下需要注意的點:
    • 如圖流程所示,我們發現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 的票據。


    6. OAuth 2.0


    #在我們實際瀏覽網站的時候,當我們登入的時候除了輸入當前網站的帳號密碼外,我們還發現可以透過第三方的QQ 或微信登錄,那麼這又是如何做到了呢,這就要談到

    OAuth### 了。 ######

    OAuth 协议又有 1.0 和 2.0 两个版本,2.0 版整个授权验证流程更简单更安全,也是目前最主要的用户身份验证和授权方式。

    6.1 什么是 OAuth 2.0?

    OAuth 是一个开放标准,允许用户授权第三方网站 (CSDN、思否等) 访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方网站;

    常见的提供 OAuth 认证服务的厂商: 支付宝、QQ、微信、微博

    简单说,OAuth 就是一种授权机制。数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据。系统从而产生一个短期的进入令牌(Token),用来代替密码,供第三方应用使用。

    令牌与密码的差异:

    令牌(Token)密码(Password) 的作用是一样的,都可以进入系统,但是有三点差异。

    • 令牌是短期的,到期会自动失效: 用户自己无法修改。密码一般长期有效,用户不修改,就不会发生变化。

    • 令牌可以被数据所有者撤销,会立即失效。

    • 令牌有权限范围(scope): 对于网络服务来说,只读令牌就比读写令牌更安全。密码一般是完整权限。

    OAuth 2.0 对于如何颁发令牌的细节,规定得非常详细。具体来说,一共分成四种授权模式 (Authorization Grant) ,适用于不同的互联网场景。

    无论哪个模式都拥有三个必要角色:客户端授权服务器资源服务器,有的还有用户(资源拥有者),下面简单介绍下四种授权模式。

    6.2 授权码模式

    授权码(Authorization Code Grant) 方式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌。

    这种方式是最常用的流程,安全性也最高,它适用于那些有后端服务的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。

    一句话概括:客户端换取授权码,客户端使用授权码换token,客户端使用token访问资源

    授权码模式的步骤详解

    • 客户端:

      打开网站 A,点击登录按钮,请求 A 服务,A 服务重定向 (重定向地址如下) 至授权服务器 (如QQ、微信授权服务)。

       https://qq.com/oauth/authorize?
         response_type=code&
         client_id=CLIENT_ID&
         redirect_uri=CALLBACK_URL&
         scope=read

      上面 URL 中,response_type 参数表示要求返回授权码(code),client_id 参数让 B 知道是谁在请求,redirect_uri 参数是 B 接受或拒绝请求后的跳转网址,scope 参数表示要求的授权范围(这里是只读)

    【總結分享】10種常用前後端鑑權方法,讓你不再迷惘

    • 授权服务器:

      授权服务网站 会要求用户登录,然后询问是否同意给予 A 网站授权。用户表示同意,这时授权服务网站 就会跳回 redirect_uri 参数指定的网址。跳转时,会传回一个授权码,就像下面这样。

      https://a.com/callback?code=AUTHORIZATION_CODE

      上面 URL 中,code 参数就是授权码。

    【總結分享】10種常用前後端鑑權方法,讓你不再迷惘

    • 网站 A 服务器:

      拿到授权码以后,就可以向 授权服务器 (qq.com) 请求令牌,请求地址如下:

       https://qq.com/oauth/token?
        client_id=CLIENT_ID&
        client_secret=CLIENT_SECRET&
        grant_type=authorization_code&
        code=AUTHORIZATION_CODE&
        redirect_uri=CALLBACK_URL

      上面 URL 中,client_id 参数和 client_secret 参数用来让授权服务器 确认 A 的身份(client_secret 参数是保密的,因此只能在后端发请求),grant_type参数的值是AUTHORIZATION_CODE,表示采用的授权方式是授权码,code 参数是上一步拿到的授权码,redirect_uri 参数是令牌颁发后的回调网址。

    1【總結分享】10種常用前後端鑑權方法,讓你不再迷惘

    • 授权服务器:

      收到请求以后,验证通过,就会颁发令牌。具体做法是向 redirect_uri 指定的网址,发送一段 JSON 数据。

       {    
         "access_token":"ACCESS_TOKEN",
         "token_type":"bearer",
         "expires_in":2592000,
         "refresh_token":"REFRESH_TOKEN",
         "scope":"read",
         "uid":100101,
         "info":{...}
       }

      上面 JSON 数据中,access_token 字段就是令牌,A 网站在后端拿到了,然后返回给客户端即可。

    1【總結分享】10種常用前後端鑑權方法,讓你不再迷惘

    6.3 隐藏式模式(Implicit Grant)

    有些 Web 应用是纯前端应用,没有后端。这时就不能用上面的方式了,必须将令牌储存在前端。OAuth2.0 就规定了第二种方式,允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤,所以称为(授权码)"隐藏式"(implicit)。

    一句话概括:客户端让用户登录授权服务器换token,客户端使用token访问资源

    隐藏式模式的步骤详解

    • 客户端:

      打开网站 A,A 网站提供一个链接,要求用户跳转到 授权服务器,授权用户数据给 A 网站使用。如下链接:

       https://qq.com/oauth/authorize?
         response_type=token&
         client_id=CLIENT_ID&
         redirect_uri=CALLBACK_URL&
         scope=read

      上面 URL 中,response_type参数为token,表示要求直接返回令牌。

    • 授权服务器:

      用户跳转到授权服务器,登录后同意给予 A 网站授权。这时,授权服务器就会跳回redirect_uri 参数指定的跳转网址,并且把令牌作为 URL 参数,传给 A 网站。

       https://a.com/callback#token=ACCESS_TOKEN

      上面 URL 中,token参数就是令牌,A 网站因此直接在前端拿到令牌。

    1【總結分享】10種常用前後端鑑權方法,讓你不再迷惘

    注意:

    • 令牌的位置是 URL 锚点(fragment),而不是查询字符串(querystring),这是因为 OAuth 2.0 允许跳转网址是 HTTP 协议,因此存在"中间人攻击"的风险,而浏览器跳转时,锚点不会发到服务器,就减少了泄漏令牌的风险。

    • 这种方式把令牌直接传给前端,是很不安全的。因此,只能用于一些安全要求不高的场景,并且令牌的有效期必须非常短,通常就是会话期间(session)有效,浏览器关掉,令牌就失效了。

    6.4 用户名密码式模式(Password Credentials Grant)

    如果你高度信任某个应用,OAuth 2.0 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为"密码式"(password)。

    一句话概括:用户在客户端提交账号密码换token,客户端使用token访问资源。

    密码式模式的步骤详解

    • 客户端:

      A 网站要求用户提供 授权服务器(qq.com) 的用户名和密码。拿到以后,A 就直接向 授权服务器 请求令牌。

       https://oauth.b.com/token?
         grant_type=password&
         username=USERNAME&
         password=PASSWORD&
         client_id=CLIENT_ID

      上面 URL 中,grant_type参数是授权方式,这里的password表示"密码式",usernamepassword授权服务器 的用户名和密码。

    • 授权服务器:

      授权服务器 验证身份通过后,直接给出令牌。

      注意,这时不需要跳转,而是把令牌放在 JSON 数据里面,作为 HTTP 回应,A 网站因此拿到令牌。

    这种方式需要用户给出自己的用户名/密码,显然风险很大,因此只适用于其他授权方式都无法采用的情况,而且必须是用户高度信任的应用。

    6.5 客户端模式(Client Credentials Grant)

    客户端模式指客户端以自己的名义,而不是以用户的名义,向授权服务器 进行认证。

    主要适用于没有前端的命令行应用。

    一句话概括:客户端使用自己的标识换token,客户端使用token访问资源

    客户端模式的步骤详解

    • 客户端:

      客户端向授权服务器 进行身份认证,并要求一个访问令牌。请求链接地址:

       https://oauth.b.com/token?
         grant_type=client_credentials&
         client_id=CLIENT_ID&
         client_secret=CLIENT_SECRET

      上面 URL 中,grant_type参数等于client_credentials表示采用凭证式,client_idclient_secret用来让授权服务器 确认 A 的身份。

    • 授权服务器:

      授权服务器 验证通过以后,直接返回令牌。

    注意:这种方式给出的令牌,是针对第三方应用的,而不是针对用户的,即有可能多个用户共享同一个令牌。

    6.5 授权模式选型

    按授权需要的多端情况:

    模式 需要前端 需要后端 需要用户响应 需要客户端密钥
    授权码模式 Authorization Code
    隐式授权模式 Implicit Grant
    密码授权模式 Password Grant
    客户端授权模式 Client Credentials

    依照用戶端類型與存取權杖擁有者分類:

    1【總結分享】10種常用前後端鑑權方法,讓你不再迷惘

    #上述主要比較淺顯的講解了OAuth2.0 的基本邏輯,如若想詳細深入的了解,可查看官方文件OAuthRFC 6749;亦可查看OAuth 2.0 概念及授權流程梳理 做比較

    7.聯合登入與信任登入



    7.1 什麼是共同登陸

    #共同登入 指同時包含多種憑證校驗的登入服務,同時,也可以理解為使用第三方憑證進行校驗的登入服務。

    通俗點講:

    對於兩個網站A 和B,在登入A 網站的時候用B 網站的帳號密碼,就是聯合登錄,或登入B 網站的時候使用A 網站的帳號密碼,也是聯合登入。

    這樣的概念其實與上面所講的 OAuth2.0 的 使用者名稱密碼式模式 認證方式類似。 最經典的莫過於APP 內嵌H5 的使用場景,當使用者從APP 進入內嵌的H5 時,我們希望APP 內已登入的使用者能夠存取H5 內受限的資源,而未登入的用戶則需要登入後才能訪問。

    這裡想法主要有兩種,一種是原生跳轉內嵌H5 頁面時,將登入態Token 附加在URL 參數上,另一種則是內嵌H5 主動透過與原生用戶端制定的協定取得應用程式內的登入狀態。

    7.2 什麼是信任登入

    #信任登入

    是指所有不需要使用者主動參與的登錄,例如建立在私有設備與使用者之間的綁定關係,憑證就是私有設備的訊息,此時不需要使用者再提供額外的憑證。信任登入又指用第三方較成熟的使用者庫來校驗憑證,並登入目前造訪的網站。

    通俗點講:

    在 A 網站有登入狀態的時候,可以直接跳到 B 網站而不用登錄,就是 信任登入


    目前較常見的第三方信任登入帳號如:QQ 號淘寶帳號、支付寶帳號、微博帳號等。

    我們不難發現 OAtuth 2.0 其實就是信任登入的縮影,因為正是有了 OAuth,我們的信任登入才得以實現。

    8. 唯一登入

    — 假設現在產品經理提一個需求:我想要實作使用者只能在一個裝置上登錄,禁止使用者重複登入;

    — 身為優秀的程式設計師的我們當然是滿足他啦! !

    8.1 什麼是唯一登錄

    #唯一登錄,指的是禁止多人同時登入同一帳號,後者的登錄行為,會導致前者斷線。

    通俗點講就是

    :A 帳號在A 電腦上登錄後,A 帳號此時又用B 電腦再次登錄,則A 電腦請求頁面時,提示「重新登入」的訊息,並跳到登入頁面1【總結分享】10種常用前後端鑑權方法,讓你不再迷惘

    8.2 唯一登入流程圖

    ##8.3 唯一登入步驟詳解
    • 使用者在客戶端A 操作:
    • 輸入帳號請求登入介面;

    後端產生對應Token 並且傳回給客戶端A,並且在服務端保存一個登入狀態;

    ##客戶端A 保存Token,並且每次請求都在header 頭中攜帶對應的Token;

    用戶在客戶端B 操作:

    ##突然使用者在客戶端B 上開始登入操作,我們會發現,步驟和在客戶端A上面的操作幾乎是一致的;

    只是後端在產生新的Token 時,要先驗證登入狀態,然後再產生對應新的Token;

    9. 掃碼登入



    ########################### ########9.1 什麼是掃碼登入############

    掃碼登入通常見於行動裝置APP 中,許多PC 端的網站都提供了掃碼登入的功能,無需在網頁上輸入任何帳號和密碼,只需要讓行動裝置APP (如微信、淘寶、QQ等等等) 中已登入使用者主動掃描二維碼 ,再確認登錄,以讓PC 端的同款應用程式快速登入的方式就是掃碼登入

    9.2 什麼是二維碼

    #二維碼 又稱二維條碼,常見的二維碼為QR Code,QR 全名為Quick Response,是一個近幾年來行動裝置上超流行的一種編碼方式,它比傳統的Bar Code條碼能存更多的訊息,也能表示更多的資料類型。

    透過上面所述,我們不難發現,掃碼登入需要三端(PC端手機端服務端)來進行配合才能達到登入成功的效果;

    9.3 掃碼登入的認證流程圖

    1【總結分享】10種常用前後端鑑權方法,讓你不再迷惘

    • 9.4 掃碼登入的步驟詳解(待掃碼階段、待確認階段、已確認階段)

    • 待掃碼階段:

      PC端:

    • 打開某個網站(如taobao.com) 或某個APP (如微信) 的掃碼登錄入口;就會攜帶PC 端的設備資訊向服務端發送一個獲取二維碼的請求;

      服務端:

      伺服器收到請求後,隨機產生一個UUID 作為二維碼ID,並將UUID 與 

      PC 端的裝置資訊

       關聯起來儲存在Redis 伺服器中,然後傳回給PC 端;同時設定一個過期時間,在過期後,使用者登入二維碼需要進行刷新重新取得。

    PC 端:

    • 收到二維碼ID 之後,將二維碼ID 以 

      二維碼的形式 展示,等待行動端掃描碼。且此時的 PC 端開始輪詢查詢二維碼狀態,直到登入成功。

      如果行動端未掃描,那麼一段時間後二維碼會自動失效。

      已掃碼待確認階段:

    • 手機端:

      #開啟手機端對應已登入

      的APP (微信或淘寶等),開始掃描辨識PC 端展示的二維碼;
    行動端掃描二維碼後,會自動取得到二維碼ID,並將行動端登入的資訊憑證(Token)和二維碼ID 作為參數傳送給服務端,此時手機必須是已登入(使用掃描登入的前提是行動端的應用為已登入狀態,這樣才可以共享登入態)。

      服務端:
    • 收到手機端發送的請求後,會將 Token 與二維碼ID

       關聯,為什麼需要關聯呢?因為,當我們在使用微信時,移動端退出時,PC 端也應該隨之退出登錄,這個關聯就起到這個作用。然後會產生一個臨時 Token,這個 Token 會回傳給行動端,一次性 Token 用作確認時的憑證。

    • 已確認階段:
    • #手機端:

      收到確認訊息後,點選確認按鈕,行動端攜帶上一步中取得的 
    • 臨時Token
    •  傳送至服務端校驗;

      ##服務端:

    • 服務端校驗完成後,會更新二維碼狀態,並且為PC 端產生一個 
    正式的Token

    ,後續PC 端就是持有這個Token 存取服務端。

    PC端:輪詢到二維碼狀態為已登入狀態,並且會取得了產生的Token,完成登錄,後續訪問都基於Token 完成。


    10. 一鍵登入(適用於原生APP)

    10.1 帳號密碼登入
    • #大家都知道,最傳統的登入方式就是使用
    • 帳號加密碼登入

      ,簡單粗暴,一般也不會出現什麼問題;

    缺點:

    ###但這種方式要求使用者要記住自己的帳號和密碼,也就是有一個記憶成本。使用者為了降低記憶成本,很可能會在不同平台使用同一套帳號密碼。從安全角度考慮,一旦某個平台的帳號密碼外洩了,就會連累到該用戶使用的其他平台。 ############另外,由於帳號和個人身分無關,這意味著同一個使用者可以註冊多個不同的帳號,也就是可能會有惡意註冊的情況發生。 ###############直到手機卡的強制實名制才得以解決! ######

    10.2 手機號驗證碼登入

    隨著無線互聯的發展以及手機卡實名制的推廣,手機號儼然已成為特別的身份證明,與帳號密碼相比,手機號碼可以更好地驗證使用者的身份,防止惡意註冊。

    但是手機號碼註冊還是需要一系列繁瑣的操作:輸入手機號碼、等待簡訊驗證碼、輸入驗證碼、點擊登入。整個流程少說二十秒,而且如果收不到短信,也就登入補了,這類問題有可能導致潛在的用戶流失。

    從安全角度考慮,也存在驗證碼洩漏的風險。如果有人知道了你的手機號,而且竊取到了驗證碼,那他也能登入你的帳號了。

    所以就有了一鍵登入動作!

    10.3 什麼是一鍵登入

    我們想一下,為什麼我們需要驗證碼?驗證碼的作用就是確定這個手機號是你的,那除了使用短信,是否還有別的方式對手機號進行認證?

    於是,就有了咱們的主角一鍵登入。

    簡訊驗證碼的作用就是證明當前操作頁面的用戶與輸入手機號的用戶為相同的人,那麼實際上只要我們能夠獲取到當前手機使用的手機卡號,直接使用這個號碼進行登錄,不需要額外的操作,這就是一鍵登入

    一鍵登入能不能做,取決於運營商是否開放相關服務;隨著運營商開放了相關的服務,我們現在已經能夠接入運營商提供的 SDK 並付費使用相關的服務。

    一鍵登入流程圖:

    1【總結分享】10種常用前後端鑑權方法,讓你不再迷惘

    #一鍵登入步驟詳解:

    • #SDK 初始化: 呼叫SDK 方法,傳入平台配置的AppKey 和AppSecret

    • 喚起授權頁:呼叫SDK 喚起授權接口,SDK 會先向運營商發起獲取手機號掩碼的請求,請求成功後跳到授權頁。授權頁會顯示手機號碼遮罩以及電信商協議給使用者確認。

    • 同意授權並登入: 使用者同意相關協議,點擊授權頁面的登入按鈕,SDK 會要求本次取號的Token,請求成功後將Token傳回給客戶端

    • 取號: 將取得到的Token 傳送到自己的伺服器,由服務端攜帶Token 呼叫操作員一鍵登入的接口,呼叫成功就返回手機號碼。服務端以手機號碼登入或註冊操作,返回操作結果給客戶端,完成一鍵登入。

    三大業者開放平台:

    注意:

    在認證過程中,需要用戶打開蜂窩網絡,如果手機設備沒有插入SIM 卡、或者關閉蜂窩網路的情況下,是無法完成認證的。所以就算接入一鍵登錄,還是要相容傳統的登入方式,允許用戶在失敗的情況下,仍能正常完成登入流程。

    總結


    在學習了解上面的 10 種鑑權方法後,我們簡單概括一下

    • HTTP 基本認證適用於內部網絡,或對安全要求不是很高的網絡;
    • Session-Cookie 適用於一般中大型的網站(行動裝置APP 除外);
    • TokenJWT 都適用於市面上大部分的企業型網站,JWT 效能會優於Token;
    • 單一登入 適用於子系統較多的大型企業網站;
    • OAuth 2.0適用於需要快速註冊使用者類型的網站;
    • 掃碼登入 適用於已完成部署了三端的企業;
    • 一鍵登入 適用於原生APP;

    本文轉載自:https://juejin.cn/post/7129298214959710244

    作者:易師傅

    #(學習影片分享:web前端

    陳述:
    本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除