當我們需要設計會員登入機制的時候,很常會面臨到該如何選擇最適合的技術在網站上?這裡將會整理出設計驗證機制的重點。

前情提要

驗證 Authentication

簡單來說就是驗證使用者的身份。

授權 Authorization

使別人有權限做事情,例如給予第三方應用程式可以用哪些服務。

憑證 Credentials

要實行驗證和授權之前,需要有東西可以證明這些事情,而這個東西就叫憑證,可以想像是你的身分證。
例如你要在凌晨的時候進去網咖或是酒吧,必須要有東西證明你是成年的。

認證機制種類

最常見的認證機制為以下三種:

  1. Cookie
  2. Session
  3. JSON Web Token

以key-value的方式儲存在瀏覽器內。

無狀態的協議

無狀態表示對處理過的事件並沒有記憶性,每個請求都是獨立的,因此也無法辨識這次的請求和上次的請求是否為同一個人。為了要確認是否是同一個瀏覽器執行請求,因此需要額外處理這些判斷,可以透過Session來判別。

儲存在Client

Server會發送一些資料到Client儲存,下次Client發送請求的時候會送給Server。
因為儲存在Client,資料可能會被用戶任意竄改,因此在使用前可以先進行檢查。

不可跨域

Cookie會綁定同一個網域,無法在別的網域獲取使用。

Session

紀錄Server與Cient狀態的一種機制,Session基於Cookie產生出Session與SessionId,Session儲存在Server,SessionId則儲存在Client。

流程

  1. Server根據用戶提供的資料創建Session
  2. 請求回到Client收到回傳的SessionId
  3. 將返回的SessionId紀錄在Cookie與Domain
  4. 當Client第二次訪問Server的時候,會將Cookie傳送到Server拿取SessionId,在查找到對應的Session驗證使用者已經登入了。

Cookie和Session比較

安全性

Session將資訊儲存在Server,相較儲存在Client的Cookie安全。

儲存資訊

Session可以儲存任意的資料類型,Cookie只能儲存字串。

時效

Session時效較短,Client關閉或是過期都會失效。
Cookie可以保持長時間的登入狀態,例如常見的默認登入。

儲存大小

Session可儲存的空間較大,但是客戶過多會佔用大量的資源。
Cookie限制儲存最大不超過4KB。

Token

Acesss Token

一種訪問時所需要的憑證。

組成

唯一Id + 時間戳記 + 簽名
UId + Time stamp + signature

特點

  1. Server不需儲存狀態,因此擴展性較高
  2. 較高的安全性
  3. 可跨域使用

流程

  1. Client要求登入
  2. Server收到請求驗證帳號密碼
  3. 驗證成功會發送Token到Client
  4. Client收到請求會儲存在Cookie或localstorage
  5. Client每次請求都會帶Token
  6. Server每次收到請求都會驗證Token

重點

  1. 每次攜帶Token都會放到Http的header
  2. 由於是Server無狀態的驗證方式,因次Server不需儲存Token,改以解析Token的時間換取儲存空間來減少Server的負擔,不需再頻繁的查詢資料庫。
  3. Token不受限於同源問題
  1. session
    紀錄Server和Client狀態的機制
    session儲存在server,session id會儲存在Client
    Session儲存在Server上,因此需要定期清除過期的
  2. JSON web token
    JWT不依賴cookie,因此不需要擔心跨域的問題
    可以用來驗證也可以用來傳送資料,

Refresh token

是一種可以刷新Access token的token,有沒有它其實都可以刷新Access token,只是每次要刷新都要使用者登入一次帳號密碼,所以他改善使用者需要額外做的一些繁瑣動作。

重點

  1. 如果過期了,那使用者還是要登入。
  2. Refresh token的過期時間儲存在Server資料庫上,只有在申請新的Access token的時候才要驗證。

Token和Session的差別

以身份驗證來說,Token的安全性比Session來得好。
如果你的產品需要支援第三方服務,用Token。
如果只需要在自己的網站上開發,都行。

JSON Web Token

JWT是目前最流行的跨網域解決方案,一般被用來傳遞使用者的資訊。
可以使用HMAC演算法或RSA公私鑰進行簽名。
首先來了解JWT解決了什麼問題,因為他是存在Client,所以他的出現不是為了解決資料安全的問題,而是為了確保資料是被本人所創建的!(無法竄改)
為什麼無法解決安全性的問題?因為header, payload是以base64的方式編碼,base64主要是為了方便傳遞資料而被使用的
Token由於會攜帶資料,所以會比cookie還大。

驗證流程

  1. Client登入,Server認證成功之後送一組JWT到Client。
  2. Client儲存JWT在local,通常是放在localstorage。
  3. 當使用者想要訪問受到保護的route或是資源的時候,需要在header的Authorization加入Bearer模式
header
1
Authorization: Bearer <token>
  1. Server的Router將會檢查Authorization
  2. JWT可夾帶使用者訊息,因此減少了訪問資料庫的動作
  3. JWT不會使用到Cookie,因此可以使用任意網域的服務
  4. 使用者的狀態不再儲存到Server,所以是一種無狀態驗證機制

JWT使用方式

  1. 放入header
    當然使用者可以放到Cookie,但是這樣就無法進行跨域,因此可以放到header的Authorization。

    1
    2
    3
    GET /calendar/v1/events
    Host: api.example.com
    Authorization: Bearer <token>
  2. 使用URL傳輸
    這是一種方式,不過不建議這麼做,因為把Token暴露給大家看到了

    1
    http://www.example.com/user?token=xxx

Token和JWT

共通點

  1. 都是一種Token
  2. 都可以記錄使用者訊息
  3. 讓Server無狀態化
  4. 驗證成功後,才能訪問資源

差異

Token

驗證Client送過來的Token時,還需要使用資料庫查詢資料,再驗證Token是否有效

JWT

將Token和payload加密後儲存在Client,Server只需要使用key進行解密,不需要額外再使用資料庫,因為JWT已經包含使用者資訊和加密訊息。

參考資料

Cookie、Session、Token、JWT
JWT suck