什麼是身分驗證?登入、工作階段與 OAuth 一次看懂
身分驗證是應用程式確認使用者身分的方式,通常是檢查使用者知道的東西(例如密碼)、擁有的東西(例如寄到手機或信箱的驗證碼),或來自可信任的其他服務的身分(例如「使用 Google 登入」)。使用者通過驗證後,應用程式會用工作階段或權杖記住他,讓他不必每一頁都重新登入。至於這位已知的使用者能做什麼,則是另一個步驟,稱為授權。
用 AI 開發時,為什麼這很重要
新增登入功能是人們向 AI 建構工具提出最常見的要求之一,也是最容易在細節上出錯的項目之一。登入頁面本身很容易產生,困難的是它周圍的一切:
- 密碼是否被安全地儲存?
- 每一個私人頁面和每一個 API 端點,是否真的檢查了是誰在提出請求?
- 已登入的客戶能不能只靠修改網址中的數字,就看到另一位客戶的資料?
- 使用者忘記密碼時會發生什麼事?
一個應用程式看起來可能很安全,但在上述每一項都可能失敗。了解這些運作的環節,能幫助你問對問題、測試對的項目。
日常生活的比喻
想像你在飯店辦理入住。
在櫃檯,你出示證件,這就是身分驗證:證明你是誰。接著櫃員給你一張房卡,這張卡就是你的工作階段(session):在整個住宿期間,你不必再出示證件,只要刷卡即可。
房卡能開你的房間、健身房和你所在樓層的電梯,但打不開其他房客的房間或員工辦公室。這就是授權:你的身分被允許存取哪些東西。如果你遺失了房卡,飯店可以在櫃檯將它停用(撤銷工作階段)。退房時,它就不能再使用了(登出或到期)。
「使用 Google 登入」就像飯店接受一位可信任的合作夥伴所寫的信,信中說「這位就是他本人」,而不是自己檢查你的證件。
主要的登入方式
| 方式 | 運作方式 | 優點 | 缺點 |
|---|---|---|---|
| 電子郵件 + 密碼 | 使用者設定密碼;應用程式儲存其雜湊值 | 大家熟悉,不依賴外部服務 | 你必須安全地儲存雜湊值,並處理重設密碼 |
| 魔術連結/一次性驗證碼 | 應用程式寄出連結或驗證碼,讓使用者登入 | 沒有密碼可以外洩或遺忘 | 依賴電子郵件送達;登入較慢 |
| 社群登入(OAuth/OpenID Connect) | 使用者以 Google、Apple、GitHub 等帳號登入 | 使用者操作快速;你不必儲存密碼 | 每個服務商都需要設定;沒有該帳號的使用者無法使用 |
| 代管的驗證服務 | 由 Clerk、Auth0 或 Supabase Auth 等服務處理註冊、登入與重設 | 你需要處理的安全工作較少 | 規模變大後會有月費;又多一個相依服務 |
| 多重驗證(MFA/2FA) | 第一道驗證之後再加一道,例如驗證器應用程式的代碼 | 大幅提高被入侵的難度 | 操作稍微麻煩一點 |
密碼應該如何儲存
安全的應用程式從來不會儲存你的實際密碼,而是儲存雜湊值(hash):也就是單向函式的輸出,它把密碼轉換成固定長度的字串。當你登入時,應用程式會對你輸入的內容做雜湊,再與儲存的雜湊值比對。
有兩個細節讓這種做法安全:
- 鹽(salt):在雜湊之前,為每個密碼加上一段隨機值。這樣即使兩個人用了相同的密碼,得到的雜湊值也不同,預先計算好的查詢表就沒有用了。
- 專為密碼設計的慢速演算法:例如 Argon2、bcrypt 或 scrypt。像 MD5 或 SHA-256 這類通用雜湊本身速度太快,攻擊者可以嘗試數十億次猜測。
雜湊與加密不同。加密過的資料可以用金鑰解密;密碼雜湊則被設計成完全無法還原。
工作階段與權杖的比較
登入之後,應用程式需要在每次請求時認出你。常見的做法有兩種。
| 工作階段(Cookie) | 權杖(例如 JWT) | |
|---|---|---|
| 瀏覽器持有的內容 | Cookie 中的隨機工作階段 ID | 經過簽章、包含使用者資訊與到期時間的權杖 |
| 登入狀態存放在哪裡 | 伺服器端,存在資料庫或儲存區 | 存在權杖本身之中 |
| 在所有裝置上登出某人 | 容易:在伺服器上刪除工作階段 | 較難:除非你另外維護封鎖清單,否則權杖在到期前一直有效 |
| 典型用途 | 傳統網頁應用程式 | API、行動應用程式、服務之間的通訊 |
對於 Cookie,有三個設定很重要:HttpOnly(頁面上的 JavaScript 無法讀取該 Cookie)、Secure(只透過 HTTPS 傳送)以及 SameSite(限制來自其他網站的請求時才會傳送)。把權杖存在瀏覽器的 localStorage 中雖然很常見,但會讓任何在頁面上執行的腳本都能讀取它。
OAuth 與「使用 Google 登入」
OAuth 2.0 是委派授權的標準:它讓應用程式取得你在另一個服務上帳號的有限存取權,例如讀取你的 Google 日曆,而且完全不會看到你的 Google 密碼。你會被導向 Google,核准特定的權限(稱為範圍(scope)),然後 Google 只會把這些權限的權杖交給應用程式。
OAuth 本身的設計目的是授予存取權,而不是說明你是誰。OpenID Connect(OIDC)是建立在 OAuth 2.0 之上的一層,增加了身分資訊,「使用 Google 登入」或「使用 Apple 登入」就是採用它。設定時,你要在服務商那裡註冊你的應用程式,取得用戶端 ID(client ID)與用戶端密鑰(client secret);密鑰必須留在你的伺服器上。
實例:客戶入口網站的登入功能
假設你正在建立一個入口網站,讓設計公司的客戶可以查看他們的專案和帳單。
- 身分驗證:客戶以電子郵件加上魔術連結登入,因此不需要管理密碼。公司員工則以 Google Workspace 帳號登入。
- 角色:每位使用者都有一個角色,即
client或staff。 - 授權規則:
| 動作 | 客戶 | 員工 |
|---|---|---|
| 查看自己公司的專案 | 可以 | 可以 |
| 查看其他公司的專案 | 不可以 | 可以 |
| 上傳檔案到專案 | 只限自己的專案 | 可以 |
| 將帳單標示為已付款 | 不可以 | 可以 |
- 在哪裡執行:在伺服器上,針對每一個請求執行。伺服器會查出登入的使用者,然後只回傳
project.company_id與該使用者所屬公司相符的專案。只隱藏「標示已付款」按鈕是不夠的,端點本身也必須拒絕請求。
常見名詞解釋
| 名詞 | 意義 |
|---|---|
| 身分驗證(AuthN) | 確認某人是誰。 |
| 授權(AuthZ) | 決定他可以做什麼。 |
| 工作階段(Session) | 應用程式在多次請求之間記住你已登入的狀態。 |
| Cookie | 瀏覽器在每次請求時回傳給網站的一小段資料。 |
| JWT | JSON Web Token:經過簽章、結構精簡的權杖,攜帶使用者 ID 與到期時間等宣告(claims)。 |
| 角色/權限 | 例如 admin 或 member 之類的標籤,用來決定存取權。 |
| MFA/2FA | 要求第二種證明,例如驗證器應用程式的代碼。 |
| SSO | 單一登入:一次登入即可使用多個應用程式(通常是公司帳號)。 |
| 401 與 403 | 「你是誰?」(未通過驗證)與「你不能這樣做」(未獲授權)。 |
常見錯誤與誤解
- 只在頁面上檢查權限。 如果瀏覽器隱藏了按鈕,但 API 沒有檢查,任何人都能直接呼叫 API。
- 相信網址中的 ID。
/invoices/1042必須檢查發票 1042 是否屬於已登入的使用者。 - 自己發明加密方式。 請使用知名的函式庫或服務商;不要讓 AI 自創雜湊機制。
- 密碼重設機制薄弱。 重設連結應該只能使用一次、很快過期,而且不應透露某個電子郵件是否有帳號。
- 把應用程式的登入與你建構工具的登入搞混。 你的應用程式使用者,與你在建構工具上的帳號是分開的。
- 登入沒有速率限制。 沒有限制的話,攻擊者可以無止盡地嘗試密碼。
該向你的 AI 建構工具要求什麼
- 「使用[知名的函式庫或服務商]新增註冊與登入功能。不要自己撰寫密碼雜湊。」
- 「使用 bcrypt 或 Argon2 雜湊儲存密碼。」
- 「工作階段的 Cookie 請使用 HttpOnly 與 Secure。」
- 「新增角色:admin 與 member。列出每一個端點,以及哪些角色可以呼叫它。」
- 「在伺服器上強制執行:使用者只能讀取與編輯自己的紀錄。然後向我展示你是如何檢查的。」
- 「新增密碼重設功能,使用一小時後過期、只能使用一次的連結。」
- 「對登入嘗試設定速率限制。」
接著自己測試:建立兩個帳號,並在以其中一個帳號登入時,嘗試存取另一個帳號的資料。我們的新增登入功能指南與安全檢查清單會提供更多細節。
Mythex 中的身分驗證
Mythex 並未提供內建的身分驗證產品給你應用程式的使用者;你需要選擇一種做法,例如在專案的資料庫中以電子郵件與密碼儲存,或使用代管服務商的 SDK,然後請代理程式幫你加入。服務商金鑰應放在專案機密中,而不是放在聊天內容裡。這與你如何登入 Mythex 本身是分開的。Mythex 文件中的為應用程式加入登入功能食譜提供可以改寫的起始提示詞,而什麼是 API則說明這些伺服器端檢查位於何處。
常見問題
身分驗證(authentication)和授權(authorization)有什麼不同?
身分驗證是確認你是誰,例如檢查你的密碼。授權則是在知道你是誰之後,決定你可以做什麼,例如能不能進入後台頁面,或能不能編輯別人的預約。應用程式兩者都需要。
什麼是 OAuth?
OAuth 2.0 是一種標準,讓應用程式在不知道你密碼的情況下,取得你在另一個服務上帳號的有限存取權。「使用 Google 登入」採用的是建立在 OAuth 2.0 之上的身分層 OpenID Connect,因此應用程式能從 Google 得知你是誰。
我的應用程式應該儲存密碼嗎?
絕對不要以可讀取的形式儲存。如果你使用電子郵件與密碼登入,密碼必須以加鹽雜湊(salted hash)的形式儲存,並使用專為密碼設計的慢速演算法,例如 Argon2 或 bcrypt。許多應用程式會改用代管的驗證服務、社群登入或電子郵件魔術連結來避開這個問題。
應用程式該用工作階段還是權杖?
兩者都可行。工作階段會在伺服器上儲存登入狀態,並把一組隨機 ID 放在 Cookie 中交給瀏覽器,很容易撤銷。像 JWT 這樣的權杖則本身就攜帶經過簽章的資訊,適合 API 與行動裝置用戶端,但在到期前比較難取消。對一般網頁應用程式來說,以 Cookie 為基礎的工作階段是穩健的預設選擇。