iT邦幫忙

2024 iThome 鐵人賽

DAY 8
0
Software Development

全端實戰心法:小團隊的產品開發大小事系列 第 8

登入系統(三):驗明身份,Session-Based 及 Token-Based 驗證

  • 分享至 

  • xImage
  •  

前面我們聊到登入系統的基本機制,大致可分為註冊、登入及驗證,而不論使用哪種登入的方式,都有一道難題要考慮:驗證使用者。

由於網站都是基於 HTTP 協定溝通的,舉個例子來說,就像是你我兩人在一群人之中傳遞紙條,當我已經確認了你是我的的會員後(也就是登入之後),我又要怎麼確認你下次傳的紙條還是你本人呢?

Client Server 登入及驗證
*Client Server 登入及驗證

在紙條 1 當中的登入動作,Server 的處理只要對照紙條上寫的 Username 及 Password,和自己資料庫裡面儲存的內容比對後,符合的話就能辨認其身份的正確性。

然而在紙條 2 當中,Client 要傳遞怎麼樣的資訊才能讓 Server 確認其身份呢?

  1. 再傳一次帳號當作簽名:這可能不是可行的方式,因為只要有人知道我們的帳號,就能也加上這個簽名來偽裝成我們

  2. 再傳一次帳號及密碼:這的確是可行的辦法,我們可以在紙條 2 想傳遞的訊息外再附上帳密,讓伺服器再驗證一次,然而每次的都傳遞密碼的行為顯然會增加資安的風險

那麼,有沒有比較好的方式?

驗證使用者

還記得我們有登入這個動作吧,如果 Server 在 Client 登入之後能夠給 Client 一組只有雙方知道的文字,就能夠不用每次都再傳輸密碼了,如果怕這組文字被竊取的話,可以定期更新它,例如每 15 分鐘就更新一次。

如此一來,我們只要在每次登入時,產生一組文字在 Server 的小本本上就能達到目標。

附帶識別碼的 Request
*附帶識別碼的 Request

而這種登入後產生識別碼的驗證方式,在實務上又大致可以分成兩種類型:Session-Based 及 Token-Based,其主要的差異在於「狀態」:例如 Server 需不需要知道有幾個 Client 是在登入當中的狀態。

Session-Based 驗證

這種能夠在 Server 端維護使用者登入「狀態」的模式就稱作 Session-Based 驗證,直譯過來就是以「會話為基礎的」。

一段會話就像是當兩個人在溝通時,我可以得知對方的狀態為何,包含我們是否正要開始對話了,在一段對話中嗎,還是已經結束對話了?而 Session-Based 的驗證也是如此,以 Server 的角度來看,我能得知 Client 是否處於登入的狀態,亦或是已經登出了。

要實作 Session-Based 的驗證,就需要在 Server 端儲存一個識別碼,通常就做 Session ID。

Session ID 用以驗證 Client 的登入狀態
*Session ID 用以驗證 Client 的登入狀態

當使用者登入後,就會產生一組唯一的 Session ID 對應至這個使用者之下。以上面的圖例來說,John 和 Jane 都在資料庫中有對應的 Session ID,他們便是「登入中」的狀態,而 David 則尚未登入。

使用 Session-Based 驗證的好處就是所有的狀態都儲存在資料庫中,你可以列出目前誰是登入的,甚至能把某人的 Session ID 移除。這也就意味著將其登入狀態抹去,就算他再拿著這組 Session ID 來讓你驗證,由於資料庫中的 Value 已經被刪去,也就無法再被成功驗證。

Token-Based 驗證

至於 Token-Based 驗證,則是不保存「狀態」的一種驗證方式。也就是說不需要資料庫來儲存我們這邊稱作 Token 的識別碼。

有這種事?不用後端的小本本記錄,也能讓使用者保持登入狀態嗎?沒錯,這涉及到前面提過雜湊的原理,我們來看看下面這個例子。

Token-Based 原理範例
*Token-Based 原理範例

當 Server 驗證過 John 的帳號密碼之後,回傳一段訊息:「John 已經登入」,並把這個訊息透過雜湊算法生成一段雜湊值,兩者組起來之後回傳給 John 類似這樣的資訊「John 已經登入 . e3659」。如果此時我們把原訊息改成「David 已經登入」,就會發現透過同樣的算法產出的雜湊值並非 e3659,也就會發現原訊息被篡改。

伺服器端就是通過只有自己知道「金鑰」的雜湊算法,產出一個 Token 給前端,只要自己能夠重新 Hash 出來相同結果,就能知道這是自己所發的 Token,並且順帶儲存一些不會被篡改的資訊,例如 Token 的 Owner 是誰、過期時間等等。

兩者比較

既然 Token-Based 這麼好用,居然不用資料庫就能驗證身份,是否用它就好?也不見得,還是得回到需求面:我們是否要保存狀態?

如果有將某 User 踢出登入狀態的需求,Token-Based 就無法達成,因為一旦發出去的 Token 我們就無法控制了,只能夠在下次接收到的時候驗證資料是否正確、沒有被篡改罷了。而 Session-Based 雖然要多維護一個資料庫,但是能做的彈性就稍微大一些。

另外值得一提的是,Token-Based 由於不用資料庫,所以在擴展性上就優於 Session-Based。因為當使用者的數量變得很大的時候,我們就不需要考慮資料庫的擴增問題,Token 想怎麼發就怎麼發。

但,基於我們是以小團隊的角度來開發,如果可以不用考慮多開一張表來儲存 Session,也不考慮登出某 User 的需求,Token-Based 的實作上會顯得簡單很多。


上一篇
登入系統(二):使用者密碼的傳遞及儲存,加密及雜湊
下一篇
登入系統(四):前端如何儲存、送出 Session ID 及 Token?
系列文
全端實戰心法:小團隊的產品開發大小事13
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言