4種常規的登陸認證方式

登陸是每一個網站中都常常用到的一個功能,在頁面上咱們輸入帳號密碼,敲一下回車鍵,就登陸了,但這背後的登陸原理你是否清楚呢?今天咱們就來介紹幾種經常使用的登陸方式。前端

  • Cookie + Session 登陸
  • Token 登陸
  • SSO 單點登陸
  • OAuth 第三方登陸

Cookie + Session 登陸

HTTP 是一種無狀態的協議,客戶端每次發送請求時,首先要和服務器端創建一個鏈接,在請求完成後又會斷開這個鏈接。這種方式能夠節省傳輸時佔用的鏈接資源,但同時也存在一個問題:每次請求都是獨立的,服務器端沒法判斷本次請求和上一次請求是否來自同一個用戶,進而也就沒法判斷用戶的登陸狀態。算法

爲了解決 HTTP 無狀態的問題,Lou Montulli 在 1994 年的時候,推出了 Cookie。數據庫

Cookie 是服務器端發送給客戶端的一段特殊信息,這些信息以文本的方式存放在客戶端,客戶端每次向服務器端發送請求時都會帶上這些特殊信息。

有了 Cookie 以後,服務器端就可以獲取到客戶端傳遞過來的信息了,若是須要對信息進行驗證,還須要經過 Session。後端

客戶端請求服務端,服務端會爲此次請求開闢一塊內存空間,這個即是 Session 對象。

有了 Cookie 和 Session 以後,咱們就能夠進行登陸認證了。api

1. Cookie + Session 實現流程

Cookie + Session 的登陸方式是最經典的一種登陸方式,如今仍然有大量的企業在使用。瀏覽器

用戶首次登陸時:
image.png安全

  1. 用戶訪問 a.com/pageA,並輸入密碼登陸。
  2. 服務器驗證密碼無誤後,會建立 SessionId,並將它保存起來。
  3. 服務器端響應這個 HTTP 請求,並經過 Set-Cookie 頭信息,將 SessionId 寫入 Cookie 中。
  4. 瀏覽器會根據Set-Cookie中的信息,自動將SessionId存儲至cookie中。
服務器端的 SessionId 可能存放在不少地方,例如:內存、文件、數據庫等。

第一次登陸完成以後,後續的訪問就能夠直接使用 Cookie 進行身份驗證了:服務器

image.png

  1. 用戶訪問 a.com/pageB 頁面時,會自動帶上第一次登陸時寫入的 Cookie。
  2. 服務器端比對 Cookie 中的 SessionId 和保存在服務器端的 SessionId 是否一致。
  3. 若是一致,則身份驗證成功。

2. Cookie + Session 存在的問題

雖然咱們使用 Cookie + Session 的方式完成了登陸驗證,但仍然存在一些問題:微信

  • 因爲服務器端須要對接大量的客戶端,也就須要存放大量的 SessionId,這樣會致使服務器壓力過大。
  • 若是服務器端是一個集羣,爲了同步登陸態,須要將 SessionId 同步到每一臺機器上,無形中增長了服務器端維護成本。
  • 因爲 SessionId 存放在 Cookie 中,因此沒法避免 CSRF 攻擊。

Token 登陸認證

爲了解決 Session + Cookie 機制暴露出的諸多問題,咱們可使用 Token 的登陸方式。cookie

Token是服務端生成的一串字符串,以做爲客戶端請求的一個令牌。當第一次登陸後,服務器會生成一個 Token 並返回給客戶端,客戶端後續訪問時,只需帶上這個 Token 便可完成身份認證。

1. Token 機制實現流程

用戶首次登陸時:

image.png

  1. 用戶輸入帳號密碼,並點擊登陸。
  2. 服務器端驗證帳號密碼無誤,建立 Token。
  3. 服務器端將 Token 返回給客戶端,由客戶端自由保存

後續頁面訪問時:

image.png

  1. 用戶訪問 a.com/pageB 時,帶上第一次登陸時獲取的 Token。
  2. 服務器端驗證 Token ,有效則身份驗證成功。

2. Token 機制的特色

根據上面的案例,咱們能夠分析出 Token 的優缺點:

  • 服務器端不須要存放 Token,因此不會對服務器端形成壓力,即便是服務器集羣,也不須要增長維護成本。
  • Token 能夠存放在前端任何地方,能夠不用保存在 Cookie 中,提高了頁面的安全性。
  • Token 下發以後,只要在生效時間以內,就一直有效,若是服務器端想收回此 Token 的權限,並不容易。

3. Token 的生成方式

最多見的 Token 生成方式是使用 JWT(Json Web Token),它是一種簡潔的,自包含的方法用於通訊雙方之間以 JSON 對象的形式安全的傳遞信息。

上文中咱們說到,使用 Token 後,服務器端並不會存儲 Token,那怎麼判斷客戶端發過來的 Token 是合法有效的呢?

答案其實就在 Token 字符串中,其實 Token 並非一串雜亂無章的字符串,而是經過多種算法拼接組合而成的字符串,咱們來具體分析一下。

JWT 算法主要分爲 3 個部分:header(頭信息),playload(消息體),signature(簽名)。

header 部分指定了該 JWT 使用的簽名算法:

header = '{"alg":"HS256","typ":"JWT"}' // `HS256` 表示使用了 HMAC-SHA256 來生成簽名。

playload 部分代表了 JWT 的意圖:

payload = '{"loggedInAs":"admin","iat":1422779638}' //iat 表示令牌生成的時間

signature 部分爲 JWT 的簽名,主要爲了讓 JWT 不能被隨意篡改,簽名的方法分爲兩個步驟:

  1. 輸入 base64url 編碼的 header 部分、 .base64url 編碼的 playload 部分,輸出 unsignedToken。
  2. 輸入服務器端私鑰、unsignedToken,輸出 signature 簽名。
const base64Header = encodeBase64(header)
const base64Payload = encodeBase64(payload)
const unsignedToken = `${base64Header}.${base64Payload}`
const key = '服務器私鑰'

signature = HMAC(key, unsignedToken)

最後的 Token 計算以下:
最後的 Token 計算以下:

const base64Header = encodeBase64(header)
const base64Payload = encodeBase64(payload)
const base64Signature = encodeBase64(signature)

token = `${base64Header}.${base64Payload}.${base64Signature}`

服務器在判斷 Token 時:

const [base64Header, base64Payload, base64Signature] = token.split('.')

const signature1 = decodeBase64(base64Signature)
const unsignedToken = `${base64Header}.${base64Payload}`
const signature2 = HMAC('服務器私鑰', unsignedToken)

if(signature1 === signature2) {
  return '簽名驗證成功,token 沒有被篡改'
}

const payload =  decodeBase64(base64Payload)
if(new Date() - payload.iat < 'token 有效期'){
  return 'token 有效'
}

有了 Token 以後,登陸方式已經變得很是高效,接下來咱們介紹另外兩種登陸方式。


SSO 單點登陸

單點登陸指的是在公司內部搭建一個公共的認證中心,公司下的全部產品的登陸均可以在認證中內心完成,一個產品在認證中心登陸後,再去訪問另外一個產品,能夠不用再次登陸,便可獲取登陸狀態。

1. SSO 機制實現流程

用戶首次訪問時,須要在認證中心登陸:

image.png

  1. 用戶訪問網站 a.com 下的 pageA 頁面。
  2. 因爲沒有登陸,則會重定向到認證中心,並帶上回調地址 www.sso.com?return_uri=a.com/pageA,以便登陸後直接進入對應頁面。
  3. 用戶在認證中心輸入帳號密碼,提交登陸。
  4. 認證中心驗證帳號密碼有效,而後重定向 a.com?ticket=123 帶上受權碼 ticket,並將認證中心 sso.com 的登陸態寫入 Cookie。
  5. a.com 服務器中,拿着 ticket 向認證中心確認,受權碼 ticket 真實有效。
  6. 驗證成功後,服務器將登陸信息寫入 Cookie(此時客戶端有 2 個 Cookie 分別存有 a.comsso.com 的登陸態)。

認證中心登陸完成以後,繼續訪問 a.com 下的其餘頁面:

image.png

這個時候,因爲 a.com 存在已登陸的 Cookie 信息,因此服務器端直接認證成功。

若是認證中心登陸完成以後,訪問 b.com 下的頁面:

image.png

這個時候,因爲認證中心存在以前登陸過的 Cookie,因此也不用再次輸入帳號密碼,直接返回第 4 步,下發 ticket 給 b.com 便可。

2. SSO 單點登陸退出

目前咱們已經完成了單點登陸,在同一套認證中心的管理下,多個產品能夠共享登陸態。如今咱們須要考慮退出了,即:在一個產品中退出了登陸,怎麼讓其餘的產品也都退出登陸?

原理其實不難,能夠回過頭來看第 5 步,每個產品在向認證中心驗證 ticket 時,其實能夠順帶將本身的退出登陸 api 發送到認證中心。

當某個產品 c.com 退出登陸時:

  1. 清空 c.com 中的登陸態 Cookie。
  2. 請求認證中心 sso.com 中的退出 api。
  3. 認證中心遍歷下發過 ticket 的全部產品,並調用對應的退出 api,完成退出。

OAuth 第三方登陸

在上文中,咱們使用單點登陸完成了多產品的登陸態共享,但都是創建在一套統一的認證中心下,對於一些小型企業,未免太麻煩,有沒有一種登陸可以作到開箱即用?

實際上是有的,不少大廠都會提供本身的第三方登陸服務,咱們一塊兒來分析一下。

image.png

1. OAuth 機制實現流程

這裏以微信開放平臺的接入流程爲例:

image.png

  1. 首先,a.com 的運營者須要在微信開放平臺註冊帳號,並向微信申請使用微信登陸功能。
  2. 申請成功後,獲得申請的 appid、appsecret。
  3. 用戶在 a.com 上選擇使用微信登陸。
  4. 這時會跳轉微信的 OAuth 受權登陸,並帶上 a.com 的回調地址。
  5. 用戶輸入微信帳號和密碼,登陸成功後,須要選擇具體的受權範圍,如:受權用戶的頭像、暱稱等。
  6. 受權以後,微信會根據拉起 a.com?code=123 ,這時帶上了一個臨時票據 code。
  7. 獲取 code 以後, a.com 會拿着 code 、appid、appsecret,向微信服務器申請 token,驗證成功後,微信會下發一個 token。
  8. 有了 token 以後, a.com 就能夠憑藉 token 拿到對應的微信用戶頭像,用戶暱稱等信息了。
  9. a.com 提示用戶登陸成功,並將登陸狀態寫入 Cooke,以做爲後續訪問的憑證。

總結

本文介紹了 4 種常見的登陸方式,原理應該你們都清楚了,總結一下這 4 種方案的使用場景:

  • Cookie + Session 歷史悠久,適合於簡單的後端架構,需開發人員本身處理好安全問題。
  • Token 方案對後端壓力小,適合大型分佈式的後端架構,但已分發出去的 token ,若是想收回權限,就不是很方便了。
  • SSO 單點登陸,適用於中大型企業,想要統一內部全部產品的登陸方式。
  • OAuth 第三方登陸,簡單易用,對用戶和開發者都友好,但第三方平臺不少,須要選擇合適本身的第三方登陸平臺。
相關文章
相關標籤/搜索