當使用者登入的時候,帳號密碼要怎麼傳給伺服器?放在網址上?放在 Header?還是放在 Body?
這篇文章會介紹三種傳遞帳號密碼的方式,告訴你為什麼有些方式很危險,以及什麼情境該用哪一種。
先搞懂 HTTP 請求的結構
在講三種方式之前,先快速了解一下 HTTP 請求長什麼樣子。
當你在瀏覽器輸入網址、按下 Enter,瀏覽器就會發送一個「HTTP 請求」給伺服器。這個請求大概長這樣:
POST https://example.com/login
Content-Type: application/json
{
"username": "kk",
"password": "1234"
}一個 HTTP 請求有三個地方可以放資料:
| 位置 | 說明 | 範例 |
|---|---|---|
| URL | 網址本身,可以在後面加上 Query 參數 | https://example.com/login?username=kk |
| Header | 請求的「附加資訊」,像是資料格式、內容長度等 | Content-Type: application/json |
| Body | 請求的「主要內容」,通常放要傳送的資料 | {"username": "kk", "password": "1234"} |
另外,HTTP 請求有不同的「方法」,最常見的是 GET 和 POST:
- GET:語意上是「取得資料」,資料放在 URL 上
- POST:語意上是「送出資料」,資料放在 Body 裡面
帳號密碼可以放在 URL、Header、Body 這三個地方的任何一個,接下來我們就來看這三種方式的差別。
方式一:放在 URL(不建議用於登入)
第一種方式是把帳號密碼放在網址的 Query 參數。
使用者在登入頁面輸入帳號 kk、密碼 1234,按下登入按鈕後,程式會把帳密組合成 Query 參數,附加在網址後面,然後用 GET 方法送出請求:
GET https://example.com/login?username=kk&password=1234等等,登入不是應該用 POST 嗎?
你可能會想:「登入明明是要『送出』帳密,送出資料不是應該用 POST 嗎?怎麼會是 GET?」
沒錯,這個想法完全正確。
一般我們學到的是:
- GET:取得資料
- POST:送出資料
但問題是,技術上 GET 也可以帶資料,只是資料必須放在 URL 上(Query 參數)。
所以有些早期的網站或偷懶的做法,會把帳密直接塞在 URL 上,用 GET 送出去。雖然技術上可以動,但這樣做既不符合語意(應該用 POST),又不安全(密碼會曝光)。
這就是為什麼我們說這種方式「不建議」。
為什麼不建議?
把帳號密碼放在 URL 上,聽起來很方便,但這是最危險的做法。
問題一:瀏覽器歷史記錄
你的瀏覽器會記錄你去過的每一個網址。
如果你用這種方式登入:
https://example.com/login?username=kk&password=1234這整串網址(包含你的密碼)就會被存進歷史記錄。
別人只要打開你的瀏覽器,看一下歷史記錄,就能看到你的密碼。
問題二:伺服器的 Log
伺服器通常會記錄每一個請求,這叫做「日誌(Log)」。
Log 裡面會記錄什麼?就是你請求的網址。
所以如果你把密碼放在 URL 上,你的密碼就會被寫進 Log 檔案裡。
重點是:Log 不是只有工程師看得到。
可能運維人員會看、可能資安人員會看、可能 Log 會被備份到其他地方⋯⋯你的密碼就這樣到處流傳。
「可是我有 HTTPS 啊?」
你可能會想:「加上 HTTPS 不就加密了?傳輸過程中別人看不到啊?」
沒錯,HTTPS 確實會加密傳輸過程,中間的人看不到。
但問題不在傳輸過程,問題在兩端:
- 你的瀏覽器會記錄(歷史記錄)
- 伺服器會記錄(Log)
HTTPS 保護的是「傳輸中」,但保護不了「存起來」的東西。
結論
永遠不要把密碼放在 URL 上。
方式二:放在 Header(Basic Auth)
第二種方式是把帳號密碼放在 HTTP Header 裡面,這就是 Basic Auth:
GET https://example.com/admin
Authorization: Basic a2s6MTIzNA==a2s6MTIzNA== 是 kk:1234 經過 Base64 編碼後的結果。
這種方式跟前面兩種不太一樣:它不是在「登入頁面」使用,而是在「訪問某個受保護的頁面」時使用。
但這邊要釐清一個很重要的觀念:Basic Auth 不是拿來做登入的。
常見的誤解
很多人以為 Basic Auth 是一種「登入方式」,其實不是。
Basic Auth 的定位是:我懶得做登入頁面,只想簡單擋一下。
Basic Auth 適合的情境
Basic Auth 通常不會用在「登入頁面」,而是用在某些不想讓外人看到的頁面,例如:
- 訂單管理後台
- 銷售數據頁面
- 內部工具
- 開發測試環境
這些頁面不需要完整的會員系統,只需要「擋一下」,讓有帳密的人才能進來。
Basic Auth 的運作方式
當你嘗試進入一個被 Basic Auth 保護的頁面:
- 伺服器回傳 401(未授權)
- 瀏覽器跳出一個醜醜的彈窗,問你帳號密碼
- 你輸入後,瀏覽器把帳密編碼,放進 Header 送出
- 伺服器驗證通過,讓你進去
整個過程不需要登入頁面,瀏覽器原生就支援。
結論
Basic Auth 是「懶人擋一下」的工具,不是拿來做正式登入的。
方式三:放在 Body(正規的登入方式)
第三種方式是把帳號密碼放在 HTTP 請求的 Body 裡面,用 POST 方法送出:
POST https://example.com/login
Content-Type: application/json
{
"username": "kk",
"password": "1234"
}使用者在登入頁面輸入帳密、按下登入按鈕,程式會把帳密包在 Body 裡面,用 POST 送出去。
跟方式一不同的是,帳密不會出現在網址上,而是藏在請求的 Body 裡面。
這是大部分網站採用的登入方式,也是正規的做法。
為什麼這是正確的做法?
不會出現在 URL 上
Body 的內容不會出現在網址列,所以:
- 不會被瀏覽器歷史記錄存下來
- 不會被伺服器的 Access Log 記錄(通常 Log 只記 URL,不記 Body)
搭配 HTTPS 更安全
Body 的內容在 HTTPS 下會被完整加密,傳輸過程中不會被看到。
而且因為不會被「存起來」,所以比 Query 參數安全得多。
登入後呢?
用 POST Body 傳帳密只是「登入」這個動作。
登入成功後,伺服器要怎麼「記住」你已經登入了?這就牽涉到:
- Session + Cookie:傳統的做法
- JWT(JSON Web Token):現代常用的做法
這些會在後面的單元介紹。
三種方式的比較
| 方式 | 帳密放哪裡 | HTTP 方法 | 安全性 | 適合情境 |
|---|---|---|---|---|
| 放在 URL | 網址的 Query 參數 | GET | ❌ 很危險 | 不建議使用 |
| 放在 Header | Authorization | GET | ⚠️ 一般 | 內部系統、臨時擋一下 |
| 放在 Body | 請求的 Body | POST | ✅ 較安全 | 正式的登入功能 |
總結
記住這幾點
- 密碼永遠不要放在 URL 上 — 會被歷史記錄和 Log 存下來
- Basic Auth(放在 Header)不是拿來做登入的 — 它是「懶得做登入頁面」時的替代方案
- 正式的登入功能把帳密放在 Body — 搭配 HTTPS 更安全
什麼時候用什麼?
- 想做正式的會員登入系統 → 放在 Body
- 想簡單擋一下內部頁面,不想寫登入頁 → 放在 Header(Basic Auth)
- 想把密碼放在 URL 上 → 不要這樣做
延伸學習
學完這篇,接下來可以看看:
- Session + Cookie:登入後怎麼「記住」使用者
- JWT:現代 API 常用的身份驗證方式
- OAuth 2.0:第三方登入(用 Google、Facebook 登入)
這篇文章介紹了傳遞帳密的三種方式,希望對你有幫助!