iT邦幫忙

2024 iThome 鐵人賽

DAY 9
0
Software Development

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

登入系統(四):前端如何儲存、送出 Session ID 及 Token?

  • 分享至 

  • xImage
  •  

上一講談到 Session-Based 及 Token-Based 的驗證,兩種方式在後端的實作方式不太一樣,Session-Based 能夠保存狀態,而 Token-Based 則無法。但在前端的實作上,無論是 Session ID 或是 Token,都需要先暫存在 Browser 當中。

而這講我們就來簡單聊聊 Browser 儲存、送出登入資訊的機制,以及儲存的資訊有沒有被洩露的風險?

在瀏覽器中儲存資料

當我們透過登入的 API 得到 Session ID 或 Token 時,為了避免重新整理或是重開視窗造成資料遺失,不會將其存在記憶體中,通常都會其他方式將其儲存下來。

在現代的瀏覽器中,有提供給 JavaScript 使用的 API,稱作 Web API。而 Local Storage 和 Cookies 便是用來暫存 Client 端資料的常見 JavaScript API。

這兩種 API 便常用來儲存 Session ID 和 Token 這種維持登入中的資訊,因為當 Browser 被關閉、重新開啟之後,這些資訊依然會存在,這就是為何當我們輸入帳號密碼登入某網站之後,下次重新開啟網頁還會是登入的狀態。

兩種方式的 API 使用都相當容易,如果要寫入一組 key-value pair,例如 token,則可以這樣撰寫:

// Local Storage
localStorage.setItem('token', 'some-token');

// Cookies
document.cookie = "token=some-token";

要取得存入的資料時,Local Storage 可以直接呼叫 localStorage.getItem;而呼叫 cookie 的 document.cookie 則會得到 key1=value1; key2=value2 這樣用 ; 分隔的字串,稍微做點處理也能到我們需要的 Value。

附帶登入資訊在 Request 當中

能夠讀取儲存在前端的登入資訊後,下一個步驟就是將此資訊附帶在送往後端的 HTTP Request 之中。

HTTP 的 Method 大致可以分成有 Body 和沒有的兩類,例如 POST 有 Body 而 GET 沒有。為了符合 HTTP 的協定內容,我們要傳輸的資料能考慮放在 URL 之中,例如 http://my.website?token=some-token;或是在 POST 這類 Method 能放在 Body 當中。

然而,放在 URL 中會有 token 存放在多個地方的資安風險,因為 Browser 會將歷史記錄儲存下來,也包含瀏覽過的 URL。

放在 Body 當中相對來說安全一些,但是在考慮到我們的前端程式可能會送出不同種 Method 的 Request,在 POST 能用而 GET 不行,就會有不一致的問題,可能也不是太好的做法。

因此,最常見的方法是將此登入資訊放在 HTTP Header 當中,這是 HTTP 專門設計來放置一些 Meta Data 的欄位。

我們可以在 Headers 的 Authorization 放入 Token,或是 X-Session-ID 放入 Session:

const headers_for_token = {'Authorization': `Bearer ${token}`};
const headers_for_session_id = {'X-Session-ID': sessionId};

其中 Authorization 用來附帶各種身份驗證的資訊,如能直接附帶帳號密碼 Basic,和 OAuth 2.0 定義的 Bearer。

而 Bearer 有攜帶的意思,意味只要此 Request 攜帶後面的 Token,無論裝置或設備都可以用此驗證。然而就算不用遵從 HTTP 的 Authorization Header 或是 OAuth 2.0 的 Bearer,只要前後端都是我們設計的,就只要想辦法在前端把 Token 放入 Header,並在後端解析即可。

如同我們可以傳遞的 Session ID:這個 X-Session-ID Header 並非 HTTP 的標準內容,由 X- 開頭的名稱是我們可以自定義的 Header。

Local Storage 及 Cookies 的差異

那麼,當我們實作登入系統時,在前端應該選用哪種方式來儲存登入資訊呢?

先來看看兩者的差異,其中 Local Storage 適合儲存比較大的資料,記錄 5MB 的資訊不在話下,但是 Cookies 卻僅僅能儲存 4KB 的資訊。

另外一個主要差異則是在於 Local Storage 儲存的資料沒有所謂的期限,只要前端程式不刪、使用者也不刪,就能一直留在上面;但是 Cookies 則一定要設定一個期限,如果不設定的話便會在視窗被關掉後資料便消失。

雖說 Cookies 存的東西少,又有期限限制,但是回到需求面,如果我們只要單純儲存 Session ID 和 Token 這麼少的資訊,完全是足夠的,並且登入資訊這類如同鑰匙的資訊,留存的時間本來便不該太長,定期更換才是更安全的做法,有了期限設定讓瀏覽器自動刪除也是相當合理的,反觀 Local Storage 需要額外寫程式來刪除過期的登入資訊。

除此之外,其實還有更多資安的原因,例如 Local Storage 在 XSS、CSRF 等攻擊上比較難以抵禦,相反的 Cookies 有其他機制能夠讓資訊的儲存和傳遞更安全。

因此,在兩者實作的難易程度不會差太多之下,我們應該因為資安問題而首選 Cookies 來儲存登入後的 Session ID 及 Token。


上一篇
登入系統(三):驗明身份,Session-Based 及 Token-Based 驗證
下一篇
登入系統(五):淺談資訊安全,同源政策及 XSS、CSRF
系列文
全端實戰心法:小團隊的產品開發大小事30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言