在前面的單元,我們學過 API Key 這種驗證方式。
API Key 很單純,就是一把金鑰,有鑰匙就能進門。
但 API Key 比較適合 Server to Server 的情境,也就是後端伺服器之間的溝通。
那如果我們想做 Client to Server 呢?例如讓使用者從瀏覽器直接驗證身份,這時候該怎麼辦?
這就是今天要介紹的 HTTP Basic Authentication(基本認證)。
API Key 的限制
在講 Basic Auth 之前,我們先回想一下 API Key 有什麼問題。
API Key 就像一把鑰匙:
- 你有鑰匙 → 可以進門
- 你沒鑰匙 → 滾
但問題是:你不知道拿著鑰匙的人是誰。
小明拿這把鑰匙可以進門,老王拿同一把鑰匙也可以進門,系統根本分不出來。
如果我們想要做「多用戶管理」,想知道現在是誰在用系統,API Key 就做不到了。
為什麼會這樣?這要從 API Key 的使用情境說起。
API Key 最常用在 Server to Server 的情境,也就是後端伺服器之間的溝通。
例如你的伺服器要去呼叫金流 API、寄信 API,這種情境下,發請求的永遠是「你的程式」,不會有其他人,所以一把 Key 就夠了。
但如果是 Client to Server 的情境就不一樣了。例如你做了一個內部後台,讓小明、老王、阿華三個同事從瀏覽器登入使用。
這時候發請求的是「人」,而且是「很多不同的人」。
你會想知道:這筆操作是誰做的?這筆資料是誰改的?
API Key 沒辦法告訴你這些,因為它只是一把鑰匙,不帶任何身份資訊。
這時候就可以用 Basic Auth 來解決這個問題。
Basic Auth 怎麼運作的?
放在 HTTP Header 裡面
在講 Basic Auth 怎麼傳遞之前,先快速複習一下 HTTP Header。
每次你發送 HTTP 請求的時候,除了網址跟資料本身,還會有一個「Header」區塊,可以放各種附加資訊。
HTTP 規範裡面已經定義好很多標準的 Header,例如:
Content-Type:告訴伺服器我傳的資料是什麼格式(JSON、HTML…)Content-Length:告訴伺服器資料有多大Host:告訴伺服器我要連的是哪個網站
這些都是「標準 Header」,HTTP 規範裡本來就有的。
但有時候你想傳一些規範裡沒有的東西,就可以自己定義 Header。慣例上會用 X- 開頭,表示這是「自訂的」。
還記得 API Key 是怎麼傳的嗎?API Key 通常就是用自訂的 Header:
X-API-Key: your-api-key-here這個 X-API-Key 不是 HTTP 標準,是大家約定俗成自己取的名字。
但 Basic Auth 不一樣,它用的是 HTTP 規範裡原本就有的標準 Header:Authorization
Authorization: Basic xxxxxxxxxx這裡有三個部分:
- Authorization:HTTP 標準的 Header,專門用來做身份驗證
- Basic:告訴伺服器「我用的是 Basic 這種驗證方式」(之後學到 JWT,這裡會換成
Bearer) - xxxxxxxxxx:這是你的帳號密碼(經過處理的,下面會講)
Token 是怎麼來的?
那個 xxxxxxxxxx 其實是這樣組成的:
帳號:密碼 → Base64 編碼 → Token舉個例子:
kk:1234 → Base64 編碼 → a2s6MTIzNA==所以最後送出去的 Header 是:
Authorization: Basic a2s6MTIzNA==為什麼要 Base64 編碼?
你可能會問:「幹嘛多此一舉?直接傳帳號密碼不就好了?」
問題是,有些人的密碼很「有個性」:
- 密碼裡有空白
- 密碼裡有
@#$%這些符號 - 密碼裡有中文
這些「奇怪的字」在 HTTP 傳輸時可能會出包。
所以我們用 Base64 編碼,把它轉成「安全的字」(只有英文字母、數字、加號、斜線、等號),這樣傳輸就不會有問題了。
記住:Base64 是「編碼」不是「加密」,可以輕鬆解回來,所以不要以為這樣就安全了!
所以 Basic Auth 怎麼解決 API Key 的問題?
現在你知道 Basic Auth 的 Token 裡面包含了「帳號」和「密碼」。
這就是它跟 API Key 最大的差別:
- kk + 1234 → 伺服器知道是 kk 本人
- ken + 5678 → 伺服器知道是 ken 本人
- 亂打的 → 掰掰
因為有帳號,所以可以做「多用戶管理」,知道是誰在用你的系統。
Challenge 機制:那個醜醜的彈窗
帳號密碼從哪裡來?
前面我們講了 Basic Auth 是透過 HTTP Header 傳送 Token,Token 裡面包含帳號和密碼。
但這邊有一個問題:這個帳號密碼要從哪裡來?
如果是 Server to Server 的情境,你可以把帳號密碼寫在後端程式或環境變數裡,反正使用者看不到。
但如果是 Client to Server 呢?例如使用者從瀏覽器發請求,你總不能把帳號密碼寫死在前端 JavaScript 裡吧?那任何人打開原始碼都看得到,超不安全。
所以有了 Challenge 機制
為了解決這個問題,Basic Auth 有一個機制叫 Challenge(挑戰)。
運作方式是這樣的:
- 使用者嘗試進入某個受保護的頁面
- 伺服器發現你沒有提供帳號密碼,就回傳一個「401 未授權」的狀態
- 瀏覽器收到這個回應後,自動跳出一個視窗問你帳號密碼
- 你填完之後,瀏覽器自動幫你把帳號密碼編碼成 Token,放進 Header 重新發送請求
白話來說就是:
伺服器跟瀏覽器說:「欸,你要進來喔?先告訴我你的帳號密碼!」
然後瀏覽器就自動跳出一個視窗問你。
長什麼樣子?
就是那個你在一些老網站或內部系統會看到的彈窗:

對,就是那個看起來很復古的東西。
Challenge 的好處
- 不用自己寫登入頁面
- 不用把帳號密碼寫死在程式裡
- 瀏覽器原生支援,超省事
伺服器怎麼存帳號密碼?
先講驗證流程
當使用者輸入帳號密碼後,瀏覽器會把它編碼成 Token,放進 HTTP Header 送出去。
收到請求的一方會:
- 從 Header 拿出 Token
- 用 Base64 解碼,得到
帳號:密碼 - 去「某個地方」比對,對了就放行,錯了就拒絕
那個「某個地方」是哪裡?通常有兩種做法。
方法一:存在資料庫
在資料庫建一張表,存所有使用者的帳號密碼:
users 資料表
─────────────────────────
| username | password |
|----------|-------------|
| kk | 1234 |
| ken | 5678 |
| admin | secret |
─────────────────────────你的後端程式收到請求後,就去資料庫查有沒有這組帳密。
適合: 使用者很多、常常變動、需要細緻的權限控制
代價: 要架資料庫、要寫驗證邏輯
方法二:寫在檔案裡(讓反向代理幫你擋)
在正式環境中,請求通常會先經過反向代理:
使用者 → Nginx(反向代理) → Express/Django(後端程式)你可以讓 Nginx 在最前面就擋掉,根本不讓請求進到你的程式。
怎麼做?在伺服器上放一個 .htpasswd 檔案:
kk:1234
ken:5678
admin:secret這個檔案是放在「伺服器主機」上的,不是放在你的程式碼 repo 裡。
舉個例子,你把網站部署到一台 Linux 伺服器上,你可以把 .htpasswd 放在某個路徑,例如 /etc/nginx/.htpasswd。
然後在 Nginx 的設定檔裡面,告訴它:「如果有人要進這個頁面,去讀 /etc/nginx/.htpasswd 這個檔案比對帳密。」
location /admin {
auth_basic "請輸入帳號密碼";
auth_basic_user_file /etc/nginx/.htpasswd;
}這樣 Nginx 就會自動幫你驗證,你的程式碼完全不用動。
適合: 使用者很少、幾乎不會變、懶得寫程式
代價: 改帳密要手動編輯檔案、沒辦法做細緻的權限控制
怎麼選?
簡單講:
- 想省事、使用者少 → 用檔案
- 要彈性、使用者多 → 用資料庫
Basic Auth 的致命缺點
講了這麼多好處,該來潑冷水了。
Base64 不是加密!
前面說過,Base64 是「編碼」,任何人拿到你的 Token 都可以輕鬆解碼:
a2s6MTIzNA== → 解碼 → kk:1234所以如果有人在網路上攔截你的請求,你的帳號密碼就直接被看光光了。
一定要配 HTTPS!
這點超級重要:永遠不要在沒有 HTTPS 的情況下用 Basic Auth!
- HTTP(沒加密)→ 裸奔,超危險 ❌
- HTTPS(有加密)→ 至少傳輸過程是安全的 ✅
快速看一下怎麼寫
前端 JavaScript
const username = 'kk';
const password = '1234';
// 組合並編碼
const token = btoa(`${username}:${password}`);
// 發送請求
fetch('https://api.example.com/data', {
headers: {
'Authorization': `Basic ${token}`
}
});用 cURL 測試
# 最簡單的寫法
curl -u kk:1234 https://api.example.com/data什麼時候該用 Basic Auth?
先釐清一個常見的疑惑
學到這裡,你可能會想:
「咦?Basic Auth 要輸入帳號密碼,我們公司的會員系統也是輸入帳號密碼,這不是一樣的東西嗎?」
答案是:不一樣!
最大的差別在於:有沒有登入頁面。
| 一般會員登入系統 | Basic Auth | |
|---|---|---|
| 畫面 | 有漂亮的登入頁面 | 瀏覽器跳出醜醜的彈窗 |
| 開發成本 | 要自己做登入頁、處理 Session | 幾乎不用寫前端 |
| 適合情境 | 對外的網站、App | 內部系統、後台工具 |
Basic Auth 的定位
想像一個情境:
你做了一個公司內部的「數據後台」,只給幾個同事看。
為了這個後台,你還要特地做一個會員系統?寫登入頁面?處理忘記密碼?
太累了吧!我只是想「擋一下」而已啊!
這時候 Basic Auth 就超好用!
你只要在後台頁面前面加一層「門禁」(技術上叫 Middleware,之後會學到),設定好哪些帳號密碼可以進來,瀏覽器就會自動跳出一個小視窗問你帳密。
不用寫登入頁面、不用做會員系統,幾行設定就搞定。
適合 vs 不適合
適合用 Basic Auth:
- 公司內部系統
- 開發測試用的 API
- 簡單的小工具後台
- 臨時擋一下的需求
不適合用 Basic Auth:
- 對外開放的網站
- 有敏感資料的系統
- 正式的產品環境
說白了,Basic Auth 就是懶人擋一下的好工具,但不適合拿來做正式的會員系統。
總結
一張圖看懂 Basic Auth

記住這幾點就夠了
- Basic Auth = 帳號 + 密碼,可以知道是誰在用
- 用 Base64 編碼,處理特殊字元問題
- 有 Challenge 機制,會跳彈窗問你帳密
- 適合內部系統,不想寫登入頁面的時候很好用
- 一定要配 HTTPS,不然帳密會被看光
- 跟會員系統不一樣,Basic Auth 是懶人擋一下的好工具
什麼時候用 Basic Auth?
當你懶得做登入頁面,只想快速擋一下的時候,Basic Auth 是你的好朋友。
但如果是正式的產品,建議學一下 JWT 或 OAuth 2.0,那才是現在業界主流的做法。
延伸學習
學完 Basic Auth,接下來可以看看:
- JWT:現在最流行的 Token 驗證方式
- OAuth 2.0:第三方登入都在用這個(像是「用 Google 帳號登入」)
- Session-based Auth:傳統網站的登入機制