基本驗證雖小,至少能確認你是誰
Web 的驗證方式百百種,如果我只要一個很簡單的身份驗證怎麼辦?今天帶大家來了解基本驗證的原理跟使用情境,也會帶大家用 Express 來實作。
基本驗證(Basic Authentication)是最早被規範(RFC2617)的 HTTP 驗證方式。
當我們在網頁服務中需要非常基本的身份驗證,如:下載課程講義前,要確認學生身份;如果真的講義被駭客拿走,損失也不會太重。這個時候就可以使用基本驗證,實作相對簡單快速。
雖然現在開發網頁服務,大多會選擇其他驗證方式(Session、JWT 等),但是了解基本驗證是一件好事。除了機制簡單以外,初學時也可以從它開始理解「將資訊放在標頭中進行驗證」的概念。
會想整理這個概念的契機,是因為 Rails 中的基本驗證有內建的方法,當初學的時候因為都包好,真的很難理解它 (是時候來還債了)。
目錄
原理
基本驗證旨在客戶端將「帳號密碼」資訊打包好,放進請求的標頭內後,就能請伺服器進行驗證。
以下這張是在瀏覽器的基本驗證流程,給各位一個大方向:
說明
基本驗證的規範中,當在瀏覽器上第一次發送請求(沒有身份資訊)或驗證失敗時,伺服器要回傳狀態碼 401 ,並攜帶 WWW-Authenticate
這個標頭來「提示」客戶端驗證:
401 Unauthorized(未授權)
WWW-Authenticate: Basic realm="如果驗證後可以存取的資源範圍"
401 未授權
代表伺服器無法確認身份,便無法授權請求。
WWW-Authenticate
此外在這個回應裡,標頭中Basic
就是使用的驗證方式,這邊是指基本驗證;realm
則是伺服器自訂的存取範圍,規範定義為「當用戶通過驗證後,屬於同一個 realm 的資源用戶都可以存取」。
「提示」客戶端驗證?
這裡的提示是指「提示瀏覽器」。瀏覽器有依照網路規範所設計,當它收到這樣的回應就會跳出內建的小視窗,來請求使用者輸入帳密。
基本上這樣就結束了。
你可以看到,關鍵就是客戶端要攜帶 Authorization: Basic XXXX
的標頭,伺服器端要解碼 Basic
後面那串資訊檢查。
此外,若就應用情境來分,基本驗證可以分成兩種:
- 從瀏覽器進行基本驗證。
- 透過 API 進行基本驗證。
從瀏覽器進行基本驗證
小明學校的課程講義網站,為了防止阿貓阿狗都可以下載講義,因此需要基本驗證(來驗證你是本校學生)才可以下載講義。
小明第一次點了課程檔案連結時,因為還沒有提供任何身份資訊,伺服器會給一個 401 未授權的回應。
當瀏覽器收到 401 且有 WWW-Authenticate 的驗證方式,都會跳出小視窗請求使用者輸入帳密。
當小明輸入正確帳密 student
和 9527
,按下送出時瀏覽器會在背後做幾件事:
- 幫我們用分號串起來
student:9527
- 將它用 base64 編碼成
c3R1ZGVudDo5NTI3
- 再幫你發送一個同樣的請求過去,但這次裡面會幫你帶這個標頭資訊:
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
,會發現跳出了這個小視窗。考考你還記不記得,為什麼會跳出小視窗?
如果我們按下取消,就會看到剛剛程式碼 26 行的「請先登入才能看!」
如果我們輸入錯誤的帳密,就會再跳一次這個小視窗。
這時候去看 Server 的 Log,你會看到解碼後的結果:
如果我們輸入正確的帳密,就會看到微積分講義~
在 Server 的 Log 也會看到解出來正確的帳號密碼:
驗證過後,重新整理微積分這頁,你會發現我們不需要再重新登入,因為瀏覽器把這個資訊記起來了。如果直接到 localhost:5000/linear_algebra
,你會發現也不用重登。
完成!
總結
驗證方式有很多種,而不同的驗證適合不同的使用情境。
如果資料不是太貴重,只是要簡單確認身份,例如下載老師的 ppt、講義等等,就很適合使用基本驗證。
如果服務涉及金流(線上課程網站、電商平台),身份驗證就必須使用更加嚴謹的方式(Session、JWT、OAuth2 等)。
俗話說「殺雞焉用牛刀」,開發時依據不同的情境來選擇最適合的驗證方式,才能讓 CP 值最高。
感謝你讀到這邊,有任何問題歡迎交流指正!