API 驗證
API 驗證

API 驗證

HTTP是一個「無狀態協議 Stateless Protocol」,也就是說,每次從客戶端(Client)對伺服器(Server)發出的請求都是獨立的,這一次的請求無法得知上一次請求的內容與資訊。

那我們要如何確認使用者是否先前已登入過,或是已通過驗證?

以下會介紹三種作法

  • Cookie
  • Cookie + Session
  • JWT


Cookie

將登入狀態寫在 Cookie 中回傳給前端,每次前端要打API求資料,都帶上這個Cookie。


缺點

不安全,Cookie 可被修改

image-20210903122301303

img


Cookie + Session

既然Cookie可被修改,那就把登入狀態放在DB(或記憶體中)吧。

首先,我們把使用者的每一段連線,例如進入網站到離開網站,稱為一個Session。DB中記錄每個Session的狀態 (例如登入者、登入狀態、自動登出時間) ,並且每筆Session資料都給一個 Session ID。

當使用者進入網站後,就會從後端得到一個帶有Session ID 的 Cookie,每次打API時,後端就可以透過Cookie中的Session ID 去 DB 查詢這個使用者的登入狀態。同理,當使用者登入時,後端也只是去改DB中這個Session的資料。


優點

後端回給前端的Cookie就只帶Session ID,因此不會有登入狀態被前端修改的疑慮


缺點

每次API都要到Session查詢這個使用者的狀態,增加消耗


image-20210903123348105


JWT (JSON Web Token)

上面兩種作法不是不安全就是要透過額外查詢來檢查使用者的狀態,所以 JWT 誕生了,JWT可以同時解決上面兩種方法的缺點,既安全、又不用將狀態存在DB中,更符合HTTP的無狀態設計概念。

JWT 的流程簡單來說跟 cookie 很像,一樣是將登入狀態紀錄在token中並存放在前端,但是在資料上做了加密及驗證,可檢查token是否有被竄改過。


image-20210903124010230image-20210903124010230


JWT 組成

JWT 是一組字串,透過小數點(.)切分成三個 Base64 編碼的部分:

  • Header: Token 的種類及產生 signature 使用的雜湊演算法
  • Payload:儲存的資訊(例如 user, isLogin)
  • Signature:secret + Header + Payload,再hash後產生

image-20210903145328553

image-20210903145417784


把產出來的 token 丟到 JWT 解碼網站,可以發現Header和Payload兩個部分都是可以被輕鬆解碼回來的,並沒有加密,所以這兩部分都不適合放重要資訊。

而Signature是唯一有做加密的,同時也是檢查前兩塊部分是否有被竄改的重要依據。

image-20210903145451336


token檢查

image-20210903155236050

image-20210903155244270


優點

  1. 可擴充性佳

    在服務擴充的情況下,session需要做多機資料共享,而jwt不需要

  2. 無狀態

    jwt 不在 Server 存任何狀態,更加符合 RESTful API 的設計原則


缺點

  1. 安全性

    jwt 的 payload 只是使用 base64 編碼的,並沒有加密,因此不能儲存敏感資料 (Session存在DB就可以放比較多東西)

  2. 效能差

    隨著需要儲存的資料越多,JWT佔用空間會越來越大,若超過4K就不能放在cookie中,要存在local storage

  3. 較難控制有效性

    無法控制已發出的 token,即使你知道 token 被盜了,也沒辦法主動將其作廢。或是發現 Token 快過期時,也只能重新發一個新 Token 並拋棄原有的 Token。