基本驗證雖小,至少能確認你是誰

Web 的驗證方式百百種,如果我只要一個很簡單的身份驗證怎麼辦?今天帶大家來了解基本驗證的原理跟使用情境,也會帶大家用 Express 來實作。

袁浩 Harry Yuan
11 min readMay 23, 2021

基本驗證(Basic Authentication)是最早被規範(RFC2617)的 HTTP 驗證方式。

當我們在網頁服務中需要非常基本的身份驗證,如:下載課程講義前,要確認學生身份;如果真的講義被駭客拿走,損失也不會太重。這個時候就可以使用基本驗證,實作相對簡單快速。

雖然現在開發網頁服務,大多會選擇其他驗證方式(Session、JWT 等),但是了解基本驗證是一件好事。除了機制簡單以外,初學時也可以從它開始理解「將資訊放在標頭中進行驗證」的概念。

會想整理這個概念的契機,是因為 Rails 中的基本驗證有內建的方法,當初學的時候因為都包好,真的很難理解它 (是時候來還債了)。

目錄

  1. 原理
  2. 應用情境一:透過瀏覽器驗證的流程
  3. 應用情境二:透過 API 驗證流程
  4. 基本驗證的優點、缺點
  5. 了解基本驗證的好處
  6. 外面有什麼服務提供基本驗證?
  7. DEMO: 實作 Express 與瀏覽器的基本驗證

原理

基本驗證旨在客戶端將「帳號密碼」資訊打包好,放進請求的標頭內後,就能請伺服器進行驗證。

以下這張是在瀏覽器的基本驗證流程,給各位一個大方向:

說明

基本驗證的規範中,當在瀏覽器上第一次發送請求(沒有身份資訊)或驗證失敗時,伺服器要回傳狀態碼 401 ,並攜帶 WWW-Authenticate 這個標頭來「提示」客戶端驗證:

401 Unauthorized(未授權) 
WWW-Authenticate: Basic realm="如果驗證後可以存取的資源範圍"

401 未授權

代表伺服器無法確認身份,便無法授權請求。

WWW-Authenticate

此外在這個回應裡,標頭中Basic 就是使用的驗證方式,這邊是指基本驗證;realm 則是伺服器自訂的存取範圍,規範定義為「當用戶通過驗證後,屬於同一個 realm 的資源用戶都可以存取」。

「提示」客戶端驗證

這裡的提示是指「提示瀏覽器」。瀏覽器有依照網路規範所設計,當它收到這樣的回應就會跳出內建的小視窗,來請求使用者輸入帳密。

基本上這樣就結束了。

你可以看到,關鍵就是客戶端要攜帶 Authorization: Basic XXXX 的標頭,伺服器端要解碼 Basic後面那串資訊檢查。

此外,若就應用情境來分,基本驗證可以分成兩種:

  1. 瀏覽器進行基本驗證。
  2. 透過 API 進行基本驗證。

從瀏覽器進行基本驗證

小明學校的課程講義網站,為了防止阿貓阿狗都可以下載講義,因此需要基本驗證(來驗證你是本校學生)才可以下載講義。

小明第一次點了課程檔案連結時,因為還沒有提供任何身份資訊,伺服器會給一個 401 未授權的回應。

當瀏覽器收到 401 且有 WWW-Authenticate 的驗證方式,都會跳出小視窗請求使用者輸入帳密。

當小明輸入正確帳密 student9527,按下送出時瀏覽器會在背後做幾件事:

  1. 幫我們用分號串起來 student:9527
  2. 將它用 base64 編碼成 c3R1ZGVudDo5NTI3
  3. 再幫你發送一個同樣的請求過去,但這次裡面會幫你帶這個標頭資訊
Authorization: Basic c3R1ZGVudDo5NTI3

伺服器收到請求時,要負責將 Authorization 內的資訊進行 Base64 解碼,檢查身份。

伺服器檢查通過後,就可以看到想要的頁面。到這邊就完成驗證了!

注意:瀏覽器會自動幫你記得資訊

之後小明瀏覽學校網頁的其他頁面(相同網域)時,瀏覽器都會自動把此資訊放Authorization 標頭中發送請求。看其他頁面時,就不需要一直重新輸入帳密了。

例如:「線性代數」的講義,在伺服器那邊被設定為同樣帳密可以存取,那小明就可以直接下載,不需要重打帳密了。

應用情境二:使用 API 的方式驗證

除了上面 瀏覽器 <-> 伺服器 的方式,基本驗證也很常透過 API 的方式實作,變成在腳本程式、第三方服務或伺服器之間進行驗證。

跟剛剛只差在,這次沒人給你神奇小視窗,也沒人幫你打包資訊,所以「帳密串接和編碼」、「放進標頭」這兩部分,要由你的程式來實作。

後面會舉幾個提供基本驗證的第三方 API ,就是使用這種方式送出請求。

基本驗證的優、缺點

優點

基本驗證的優點是簡單、很好實作。通常在公司、學校內部需要一個很基本的驗證時,就不用花太多時間做。但是,有一些缺點需要特別留意。

缺點:本身沒有加密,有安全疑慮

首先 Base64 只是一種「編碼」方法,讓我們把資料轉成方便傳輸的格式,他並沒有使用任何雜湊、演算法加密

任何一個會寫程式的路人,取得該字串都可以直接解碼。以下範例是我隨便開一個 ruby 的程式,只要有這串隨便都可以解碼。

當網站是使用 HTTP 而非 HTTPS 時,請求的過程就有可能被駭客竊取資訊。駭客若拿到這些請求資訊,甚至根本不用解碼,直接跟你做「一樣的動作」就好,一樣可以騙過 Server 成功取得資源,就是所謂的「Replay Attack」。

雖然我也不懂為何駭客要微積分講義就是了

所以如果要用基本驗證,為了不讓壞蛋輕易竊取資訊,一定要搭配其他措施,例如:讓服務使用 HTTPS 加密管道、檢查使用者來源 IP 等等

缺點二:難以讓使用者登出

主要是談使用瀏覽器的情境。因為基本驗證的規範中,並沒有提供伺服器一個「提示使用者登出」的管道。

只要用瀏覽器登入過基本驗證,編碼後的資訊會一直存在瀏覽器中。除非你清除瀏覽器資料、伺服器那邊修改帳密才會真的「被登出」。

舉例來說,如果你今天是使用公用電腦,就很難直接登出,下一個人來用這台電腦,就會自動使用上一個人的驗證資訊。

缺點三:「每次送出」沒加密的資訊,更可能暴露使用者資訊

因為瀏覽器在同網域驗證過後,繼續在上面瀏覽的話瀏覽器在每次請求都會幫你帶上帳密資訊 Authorization: Basic xxxx。又因為沒有被加密,這樣每次都幫你送,帳密資訊更容易被暴露。

了解基本驗證的好處

某些情況下使用基本驗證的 CP 值會比較高。例如:在本身具有保護機制下(IP 存取限制、存取紀錄監控、HTTPS 、會定期換帳密…等)的公司、學校內網,可以快速地建立身份驗證功能,甚至不需要花時間刻 UI。

或者,若資料不是那麼重要(如上面課程講義),如果真的不小心被駭客取得,好像損失也不大。算是一個「防君子不防小人」的驗證方式。

也許你是做產品不一定會用到,但是一定要知道基本驗證的運作原理。不論是學習後面較複雜一些的驗證機制 (JSON Web Token、OAuth 2.0 )等等,我們就能先有個概念:「驗證資訊,是放在請求標頭中」。

其實,有蠻多的第三方服務、工具、程式套件都有提供這個驗證方式。若了解基本驗證,就可以先行快速地測試服務。下面找幾個例子給各位。

外面有什麼服務提供基本驗證?

有蠻多第三方服務有提供基本驗證的方式,一般多是讓開發者用來方便測試使用,也有提供其他更嚴謹的方式(JWT、OAuth 2 等)。

Twitter 開發者 API

WhatsApp 開發者 API

Github 開發者 API

你可以看到他們提醒你請使用在測試環境!

Elasticsearch 的 Kibana

Elasticsearch 是一種資料檢索引擎,有時會被歸類成 NoSQL 資料庫。他的主控台 Kibana 也有提供基本驗證。

好了,實在是太多了,分享到這就好。

要再三強調,基本驗證本身並不保證過程是安全的。若真的要在 production 環境使用基本驗證,必須要有適合的環境、或是純測試使用。

DEMO:實作 Express 與瀏覽器的基本驗證

這邊就用大家比較熟悉且常用的 Express 來實作看看吧! 對 Rails 實作有興趣的話,我會放在另一篇文章

STEP1:開新的專案

打開你的 terminal。建立一個叫 demo_express 的資料夾。接著進去安裝 express 以及建立一個 index.js 檔案。

mkdir demo_express
cd demo_express
yarn init
yarn add express
touch index.js

STEP2:基本架構

打開 index.js ,做一個最苗條的 express 架構:

啟動、檢查運作:

STEP4: 加上想要的資源路徑

就是 10 ~ 28 行,我加了兩個 route ,分別是微積分跟線性代數,目前他們都還沒有驗證檢查。這邊範例只是回傳一個 HTML 字串,就不做真的講義了xD

STEP5: 加上基本驗證

這邊就不用套件,而是自己做看看。

第 10 ~ 29 行製作了一個中介軟體 authMiddleware,講白了就是一個過濾用的 function 。我們可以將它掛在想要的 route 上,除了能達到「預先處理」的功能,也能重複使用。

這邊想要把「微積分」跟「線性代數」這兩個 route,都加上身份檢查。所以 33 跟 44 行中間掛上 authMiddleware ,讓它們在請求時會「先檢查身份」。

STEP6: 重啟 Server,試試看驗證

在瀏覽器打開 localhost:5000/calculus ,會發現跳出了這個小視窗。考考你還記不記得,為什麼會跳出小視窗?

因為瀏覽器認得 401 與 www-authenticate 標頭

如果我們按下取消,就會看到剛剛程式碼 26 行的「請先登入才能看!」

如果我們輸入錯誤的帳密,就會再跳一次這個小視窗。

這時候去看 Server 的 Log,你會看到解碼後的結果:

因為程式碼第 17 行有印出來

如果我們輸入正確的帳密,就會看到微積分講義~

只是 demo,就沒放真的講義了xD

在 Server 的 Log 也會看到解出來正確的帳號密碼:

驗證過後,重新整理微積分這頁,你會發現我們不需要再重新登入,因為瀏覽器把這個資訊記起來了。如果直接到 localhost:5000/linear_algebra ,你會發現也不用重登。

完成!

總結

驗證方式有很多種,而不同的驗證適合不同的使用情境。

如果資料不是太貴重,只是要簡單確認身份,例如下載老師的 ppt、講義等等,就很適合使用基本驗證。

如果服務涉及金流(線上課程網站、電商平台),身份驗證就必須使用更加嚴謹的方式(Session、JWT、OAuth2 等)。

俗話說「殺雞焉用牛刀」,開發時依據不同的情境來選擇最適合的驗證方式,才能讓 CP 值最高。

感謝你讀到這邊,有任何問題歡迎交流指正!

--

--

袁浩 Harry Yuan

Software Engineer | Ruby on Rails 喜歡學習前後端技術。希望文章白話到阿嬤都看得懂。