高風險操作重新驗證
很多登入系統會犯一個錯:
使用者已經登入了,所以所有操作都可以直接做。這在一般瀏覽頁面可能沒問題。
但如果操作變成:
- 修改密碼。
- 修改手機號碼。
- 新增收款帳號。
- 匯出個資。
- 查看醫療資料。
- 申請政府服務。
- 停用 MFA。
- 綁定新的第三方登入。
- 執行管理員高權限操作。
那只靠「目前 session 還有效」通常不夠。
原因很簡單:
Session 有可能被劫持。
電腦有可能暫時離開本人控制。
登入可能發生在很久以前。
目前操作的風險可能高於原本登入時的風險。所以高風險操作常需要重新驗證,也就是:
Step-up Authentication / Reauthentication這篇要回答:
- 什麼是高風險操作重新驗證?
- 它和一般登入、MFA、數位簽章差在哪?
- 哪些操作應該觸發重新驗證?
- 重新驗證後要不要重新建立 session?
- Step-up token 怎麼設計?
- 前後端流程怎麼做才不會變成安全假象?
一、 一句話回答
如果面試官問:
高風險操作為什麼要重新驗證?怎麼設計?
可以先回答:
已登入只代表目前 session 曾經通過身份驗證,不代表使用者現在仍在控制該 session,也不代表這個 session 足以執行所有敏感操作。高風險操作重新驗證是在使用者執行修改密碼、修改 MFA、變更收款帳號、查看敏感資料、提交申請等操作前,要求使用者再用密碼、MFA、Passkey、TW FidO 或其他高強度方式確認身份。驗證通過後,系統可以發一個短效、單用途、綁定操作的 step-up token,並記錄 audit log;但它仍不等於數位簽章,若要表示對文件或交易內容承諾,還需要額外簽章流程。
短一點可以說:
重新驗證是確認「現在這個人仍然有權做這個敏感操作」。二、 重新驗證解決什麼問題
登入和 session 解決的是:
這個使用者曾經通過驗證,系統可以在一段時間內識別他。但高風險操作還需要問:
這個操作夠敏感嗎?
現在是否仍然是本人?
目前登入強度夠嗎?
這次操作是否需要更強證據?重新驗證可以降低幾種風險:
| 風險 | 說明 |
|---|---|
| Session 被偷 | 攻擊者拿到 cookie / token 後,不能直接改密碼或提款 |
| 使用者離席 | 使用者忘記鎖螢幕,別人不能直接操作敏感功能 |
| 長時間登入 | 登入已經過很久,系統需要確認本人仍在 |
| 裝置或地點異常 | 新 IP、新裝置、高風險環境需要提高驗證強度 |
| 權限變更 | 修改安全設定前應再次確認 |
| 社交工程 | 攻擊者誘導使用者點擊敏感操作時,重新驗證可多一道阻擋 |
NIST SP 800-63B 也把重新驗證放在 session 管理裡,要求依 assurance level、整體時間與閒置時間重新確認使用者是否仍控制 session。
OWASP Authentication Cheat Sheet 也建議在帳號恢復、密碼重設、可疑行為、修改敏感帳號資訊、變更付款資訊、新增信任裝置等高風險事件後觸發重新驗證。
三、 重新驗證和登入、MFA、簽章的差異
| 概念 | 解決的問題 | 產物 |
|---|---|---|
| 登入 Authentication | 使用者是誰? | session / token |
| MFA | 登入或操作時使用多因素提高身份可信度 | MFA verification result |
| 重新驗證 Reauthentication | 目前 session 是否仍由本人控制?是否足以做敏感操作? | step-up result / short-lived grant |
| 風險式驗證 Risk-based Auth | 根據風險決定是否提高驗證強度 | risk decision |
| 數位簽章 Digital Signature | 誰對哪份內容簽署? | signature / content hash / evidence |
重新驗證可以使用 MFA。
例如:
修改密碼前要求再輸入目前密碼
新增收款帳號前要求 TOTP
匯出醫療資料前要求 TW FidO
管理員刪除使用者前要求 Passkey但重新驗證本身不是數位簽章。
它通常只代表:
這次敏感操作前,系統重新確認了操作者身份。如果要代表:
使用者簽署某份申請書或合約。那還要回到前一篇的數位簽章設計。
四、 哪些操作應該要求重新驗證
可以用一個簡單準則:
如果這個操作一旦被攻擊者執行,會造成帳號接管、金錢損失、個資外洩、法律效果或不可逆影響,就應該考慮重新驗證。常見類別如下。
1. 帳號安全設定
- 修改密碼。
- 修改 Email。
- 修改手機。
- 啟用 / 停用 MFA。
- 產生 backup codes。
- 新增 Passkey。
- 刪除 Passkey。
- 新增可信裝置。
- 查看或重設 recovery key。
這類操作直接影響帳號控制權。
如果攻擊者拿到 session,第一件事通常就是改掉恢復方式或停用 MFA。
2. 金流與交易
- 新增收款帳號。
- 修改付款方式。
- 提款。
- 大額轉帳。
- 建立定期扣款。
- 修改發票或稅務資訊。
金流場景通常不只需要重新驗證,某些情況還需要交易簽章或額外風控。
3. 個資與敏感資料
- 查看完整身分證字號。
- 查看醫療紀錄。
- 匯出大量個資。
- 下載報表。
- 查看 API key。
- 查看金鑰或 webhook secret。
這類操作的風險是資料外洩。
即使攻擊者不能改資料,只要能看資料也可能造成嚴重損害。
4. 政府、醫療、金融申辦
- 送出線上申請。
- 查詢健保或醫療資料。
- 授權代理人。
- 修改戶籍、稅務、保險相關資料。
- 提交具有法律效果的表單。
這類操作通常要分清楚:
重新驗證
數位簽章
授權資格檢查它們可能都需要,但不是同一件事。
5. 後台高權限操作
- 修改使用者角色。
- 新增管理員。
- 刪除資料。
- 匯出客戶名單。
- 調整安全設定。
- 產生 production token。
- 修改金流或通知設定。
後台系統尤其需要 step-up authentication,因為一個管理員 session 被劫持,影響面可能是全站。
五、 什麼時候觸發重新驗證
重新驗證不只看操作類型,也可以看情境。
| 觸發條件 | 例子 |
|---|---|
| 操作敏感 | 修改密碼、匯出資料、提款 |
| 距離上次驗證太久 | 登入超過 30 分鐘後才修改安全設定 |
| session 閒置太久 | 使用者長時間沒操作 |
| 裝置異常 | 新裝置、新瀏覽器、裝置指紋變化 |
| 網路異常 | IP 國家變更、VPN、Tor、資料中心 IP |
| 行為異常 | 短時間大量操作、速度不像人類 |
| 權限異常 | 嘗試使用不常用的管理功能 |
| 帳號狀態改變 | 剛重設密碼、剛恢復帳號 |
這就是 risk-based authentication 的延伸。
不要把所有功能都做成每一步都要重新驗證。
比較好的體驗是:
普通操作不打擾
敏感操作才提高驗證強度
風險越高,驗證越強六、 Step-up Authentication 流程
典型流程:
重點是:
敏感 API 自己要檢查重新驗證狀態,
不能只靠前端是否顯示了重新驗證畫面。前端只是體驗。
後端才是安全邊界。
七、 Step-up Token 怎麼設計
重新驗證通過後,可以發一個短效授權。
它可以是 server-side grant,也可以是短效 token。
概念:
type StepUpGrant = {
userId: string
sessionId: string
purpose: 'change_phone'
assuranceLevel: 'aal2'
verifiedBy: 'totp'
verifiedAt: string
expiresAt: string
nonce: string
}設計重點:
| 設計 | 原因 |
|---|---|
| 短效 | 減少被盜後可用時間 |
| 綁定 session | 避免拿到 grant 後換 session 使用 |
| 綁定 user | 避免跨帳號使用 |
| 綁定 purpose | 修改手機的 grant 不能拿去提款 |
| 可單次使用 | 防止重放 |
| 記錄驗證方式 | 方便稽核與風控 |
| 保存 request id | 方便追查 |
不要發一個通用的:
reauthenticated=true,有效一天。這樣會讓重新驗證失去精準性。
八、 要不要旋轉 Session
OWASP 對高風險事件後的重新驗證,建議搭配安全 session 管理,例如重新驗證後旋轉 token 或 session id。
實務上可以分兩種場景。
1. 普通 step-up 操作
例如:
查看完整手機號碼
下載一份報表可以只發短效 step-up grant,不一定要重建整個 session。
2. 帳號安全狀態變更
例如:
修改密碼
停用 MFA
新增 Passkey
重設 recovery key這類操作會改變帳號安全狀態,建議:
- 重新驗證。
- 旋轉目前 session id。
- 撤銷其他裝置 session。
- 撤銷 refresh token。
- 發送安全通知。
- 記錄 audit log。
尤其是修改密碼後,通常應提供:
登出其他所有裝置或者依風險直接強制撤銷其他 session。
九、 驗證方式怎麼選
不是所有操作都需要同一種驗證方式。
可以依風險分層:
| 風險 | 操作 | 建議重新驗證 |
|---|---|---|
| 低 | 查看一般資料 | 不需要,或只檢查 session 新鮮度 |
| 中 | 修改暱稱、地址 | 密碼或已登入 session + recent auth |
| 高 | 修改手機、停用 MFA | 密碼 + MFA / Passkey |
| 很高 | 大額交易、政府申辦、醫療授權 | 高強度 MFA、TW FidO、自然人憑證、交易簽章 |
| 管理員高風險 | 刪除資料、新增 admin | Passkey / MFA + 操作審核 + audit log |
常見方法:
- 輸入目前密碼。
- Email OTP。
- SMS OTP。
- TOTP。
- Backup code。
- Passkey / WebAuthn。
- TW FidO。
- 自然人憑證。
但要注意:
重新輸入密碼不是萬能。如果攻擊者本來就是用密碼登入,修改 MFA 前只要求同一組密碼,保護效果有限。
對高風險操作,更好的方式通常是:
不同因素 + 更強抗釣魚能力。例如 Passkey、硬體金鑰、TW FidO 或 TOTP,會比只要求再輸入密碼更好。
十、 Recent Authentication
很多系統不會每次都要求完整重新驗證,而是看:
使用者是否在最近一段時間內完成過高強度驗證。例如:
function requireRecentAuth(session: Session, maxAgeMinutes: number) {
if (!session.lastStrongAuthAt) return false
const maxAge = maxAgeMinutes * 60 * 1000
return Date.now() - session.lastStrongAuthAt.getTime() <= maxAge
}可以設計成:
| 操作 | recent auth window |
|---|---|
| 修改個人資料 | 15 分鐘 |
| 修改手機 / Email | 5 分鐘 |
| 停用 MFA | 每次都重新驗證 |
| 大額交易 | 每筆交易都要 step-up 或簽章 |
| 管理員刪除資料 | 每次都重新驗證 |
這樣可以平衡安全與體驗。
但要避免:
使用者剛登入一次,接下來 24 小時所有敏感操作都不用重新驗證。時間窗越長,風險越高。
十一、 後端 API 要怎麼檢查
前端可以顯示重新驗證 modal,但後端一定要強制檢查。
錯誤:
// 只靠前端控制按鈕
if (uiState.reauthenticated) {
showChangePasswordButton()
}正確:
async function changePassword(req: Request) {
const session = await requireSession(req)
const grant = await stepUpGrants.verify({
token: req.headers['x-step-up-token'],
userId: session.userId,
sessionId: session.id,
purpose: 'change_password'
})
if (!grant) {
throw new ReauthRequiredError('change_password')
}
await passwordService.changePassword(session.userId, req.body.newPassword)
await sessions.rotate(session.id)
await sessions.revokeOtherSessions(session.userId, session.id)
await auditLog.record(session.userId, 'password_changed')
}每個敏感 API 都應該自己檢查:
- session 是否有效。
- user 是否有權限。
- 是否需要重新驗證。
- step-up grant 是否有效。
- grant 是否綁定該操作。
- grant 是否過期或已使用。
- 風險是否仍可接受。
十二、 Audit Log 要記什麼
高風險操作一定要記錄 audit log。
至少包含:
| 欄位 | 用途 |
|---|---|
| user_id | 誰操作 |
| session_id | 哪個 session |
| action | 做了什麼 |
| target_type / target_id | 影響哪個資源 |
| reauth_required | 是否要求重新驗證 |
| reauth_method | 使用哪種驗證方式 |
| reauth_at | 重新驗證時間 |
| risk_score | 當時風險分數 |
| ip | 來源 IP |
| user_agent | 裝置資訊 |
| result | 成功 / 失敗 |
| request_id | 追蹤用 |
資料表概念:
create table security_audit_events (
id uuid primary key,
user_id uuid not null,
session_id uuid,
action text not null,
target_type text,
target_id text,
reauth_required boolean not null,
reauth_method text,
risk_score integer,
ip inet,
user_agent text,
result text not null,
request_id text not null,
created_at timestamp not null
);安全事件也應該觸發通知。
例如:
- 密碼已修改。
- MFA 已停用。
- 新裝置已登入。
- 新增 Passkey。
- 新增收款帳號。
- 管理員權限已變更。
通知內容不要洩漏敏感資料,但要讓使用者能快速發現異常。
十三、 使用者體驗怎麼設計
重新驗證不能做得像懲罰使用者。
好的體驗是:
只有在必要時出現,
清楚說明正在保護哪個操作,
驗證完成後回到原本流程。例如:
為了保護你的帳號,修改手機號碼前需要再次確認身份。不要寫:
錯誤,請重新登入。重新驗證完成後應該:
- 保留使用者已填寫內容。
- 回到原本操作。
- 不要讓使用者重新走整個流程。
- 錯誤訊息不要透露太多安全細節。
- 支援合理的備援方式。
如果驗證失敗多次:
- 限制重試。
- 提高風險分數。
- 發送安全通知。
- 必要時暫停敏感操作。
十四、 和 CSRF、XSS 的關係
重新驗證不是 CSRF 或 XSS 的替代品。
它只是多一道保護。
敏感操作仍要有:
- CSRF 防護。
- SameSite cookie。
- HttpOnly cookie。
- XSS 防護。
- rate limit。
- idempotency key。
- 權限檢查。
例如 CSRF 攻擊可能誘導使用者送出請求。
如果敏感 API 要求 step-up token,而且 token 不是攻擊者能取得的,攻擊難度會提高。
但如果網站有 XSS,攻擊者可能在使用者完成重新驗證後偷走可用 token。
所以重新驗證不能單獨存在。
十五、 和數位簽章的界線
重新驗證回答:
這次敏感操作前,系統再次確認了操作者身份。數位簽章回答:
這個人對特定內容留下可驗證簽署證據。例如:
修改手機號碼通常重新驗證即可。
但:
簽署線上申請書
大額轉帳
同意醫療授權
提交具法律效果文件可能需要重新驗證加上交易簽章或數位簽章。
可以這樣判斷:
| 需求 | 應該用 |
|---|---|
| 確認目前仍是本人操作 | 重新驗證 |
| 提高某個操作的登入強度 | Step-up authentication |
| 記錄誰做了敏感操作 | Audit log |
| 對特定文件或交易留下可驗證承諾 | 數位簽章 / 交易簽章 |
十六、 常見錯誤
1. 所有敏感操作只靠登入狀態
錯誤:
只要 session 有效,就可以修改密碼和停用 MFA。正確:
高風險操作要檢查 recent auth 或要求重新驗證。2. 只在前端做重新驗證
錯誤:
前端顯示 modal,通過後才打 API。正確:
後端 API 必須驗證 step-up grant。3. Step-up token 太通用
錯誤:
reauthenticated=true,有效 24 小時。正確:
短效、單用途、綁定 session、綁定操作。4. 修改安全設定後不撤銷其他 session
錯誤:
密碼改完,但舊裝置仍全部在線。正確:
視風險撤銷其他 session / refresh token,並通知使用者。5. 把重新驗證當成簽章
錯誤:
送出申請前有重新驗證,所以等同簽署申請書。正確:
重新驗證只是確認身份;簽章要對特定內容產生可驗證證據。6. 驗證方式和風險不匹配
錯誤:
停用 MFA 只要求 Email OTP。正確:
高風險安全設定應要求更強因素,例如目前密碼 + 已啟用 MFA / Passkey。十七、 面試追問題庫
Q1:什麼是高風險操作重新驗證?
高風險操作重新驗證是指使用者已登入後,在執行敏感操作前,系統再次確認操作者身份,避免 session 被盜、使用者離席或長時間登入造成的風險。
Q2:哪些操作需要重新驗證?
修改密碼、修改 Email 或手機、停用 MFA、新增 Passkey、查看敏感資料、匯出個資、新增收款帳號、大額交易、提交政府或醫療申請、後台高權限操作等。
Q3:重新驗證和 MFA 有什麼關係?
重新驗證是一個流程目的,MFA 是可用的驗證手段之一。高風險操作可以要求使用者用 TOTP、Passkey、TW FidO 或其他因素完成重新驗證。
Q4:重新驗證和數位簽章差在哪?
重新驗證確認目前操作者身份,數位簽章是對特定文件或交易內容留下可驗證簽署證據。重新驗證不等於簽章。
Q5:Step-up token 要怎麼設計?
應該短效、單用途、綁定 user、綁定 session、綁定 purpose,可單次使用,並保存驗證方式、驗證時間與 request id。
Q6:重新驗證後要不要重建 session?
普通敏感操作可以只發短效 step-up grant;如果是修改密碼、停用 MFA、新增安全因素等帳號安全狀態變更,建議旋轉 session id,並視風險撤銷其他 session 或 refresh token。
Q7:怎麼避免重新驗證造成體驗很差?
不要所有操作都要求重新驗證,而是根據操作敏感度、recent auth、裝置、地點、行為風險決定。驗證完成後應回到原流程,保留使用者已填內容。
十八、 實作題
題目一:設計修改手機號碼流程
好的流程:
- 使用者已登入。
- 進入修改手機頁。
- 後端判斷這是敏感操作。
- 若最近未完成強驗證,回傳
reauth_required。 - 使用者完成密碼 + MFA 或 Passkey 驗證。
- 後端產生短效 step-up grant,purpose 為
change_phone。 - 使用者輸入新手機。
- 系統對新手機送 OTP。
- OTP 驗證通過後更新手機。
- 旋轉 session 或更新安全狀態。
- 記錄 audit log。
- 通知舊手機或舊信箱。
題目二:設計停用 MFA 流程
好的答案應提到:
- 停用 MFA 是高風險操作。
- 不能只靠目前 session。
- 要求強重新驗證。
- 最好要求現有 MFA 或 backup code。
- 停用後撤銷相關 backup codes。
- 發送安全通知。
- 記錄 audit log。
- 可加入冷卻期或風險審核。
題目三:實作 API 防護
敏感 API 應該像這樣:
async function disableMfa(req: Request) {
const session = await requireSession(req)
await requirePermission(session.userId, 'mfa:disable')
const grant = await requireStepUpGrant({
token: req.headers['x-step-up-token'],
userId: session.userId,
sessionId: session.id,
purpose: 'disable_mfa',
maxAgeSeconds: 300
})
await mfaService.disable(session.userId)
await stepUpGrants.consume(grant.id)
await sessions.rotate(session.id)
await auditLog.record({
userId: session.userId,
action: 'mfa_disabled',
reauthMethod: grant.verifiedBy,
result: 'success'
})
}重點:
不是前端說通過就通過,
而是後端針對敏感操作驗證 step-up grant。十九、 資深視角
1. 重新驗證是操作級安全,不只是登入級安全
初階工程師常把安全停在:
有登入就好。資深工程師會把操作分級:
普通操作
敏感操作
高風險操作
具有法律效果的操作然後為不同操作配置不同的驗證強度、記錄、通知與補救流程。
2. 不要讓使用者替系統風險買單
如果每個按鈕都要重新驗證,使用者會疲乏。
最後他們會機械式按掉所有確認,安全反而下降。
好的設計是:
平常安靜,
關鍵時刻清楚且堅定。3. Step-up grant 要像權限票券一樣嚴格
重新驗證通過後,不要只在 session 上掛一個永久旗標。
它應該更像:
針對某個操作、某個 session、某段短時間發出的臨時授權。這樣才能降低重放與濫用風險。
4. 安全事件要能追蹤和補救
重新驗證不是流程結束。
高風險操作後還需要:
- audit log。
- 安全通知。
- session 撤銷。
- 風險分數更新。
- 異常告警。
- 使用者補救入口。
這些才讓整個身份系統有營運能力。
總結
| 問題 | 回答重點 |
|---|---|
| 為什麼要重新驗證 | 已登入不代表目前仍是本人,也不代表足以做敏感操作 |
| 什麼操作需要 | 帳號安全、金流、敏感資料、政府醫療申辦、後台高權限 |
| 使用什麼方式 | 密碼、MFA、Passkey、TW FidO、自然人憑證,依風險選擇 |
| Step-up token | 短效、單用途、綁定 user / session / purpose |
| 後端責任 | 每個敏感 API 強制檢查,不相信前端狀態 |
| Session 管理 | 安全狀態變更後應考慮旋轉與撤銷 |
| 和簽章差異 | 重新驗證確認身份,簽章綁定特定內容 |
一句完整的面試回答可以是:
高風險操作重新驗證是指使用者已登入後,在執行修改密碼、停用 MFA、修改手機、新增收款帳號、查看敏感資料、提交申請或管理員高權限操作前,系統再次確認目前操作者身份。原因是 session 可能被劫持、使用者可能離席、登入時間可能太久,或該操作風險高於原本登入強度。實作上,敏感 API 應由後端判斷是否需要 step-up authentication,使用密碼、MFA、Passkey、TW FidO 等方式重新驗證;驗證通過後發出短效、單用途、綁定 user、session 和 purpose 的 step-up grant,執行操作後記錄 audit log,必要時旋轉 session、撤銷其他裝置並通知使用者。但重新驗證不等於數位簽章,若要對文件或交易內容留下可驗證承諾,仍需要交易簽章或數位簽章流程。
延伸閱讀
- 下一篇:如何設計一個登入系統
- 前一篇:身份驗證與數位簽章
- 專題總覽:身份驗證與登入系統設計
- 相關專題:MFA 與 2FA 總覽
- 相關專題:Risk-based Authentication
- 相關專題:Cookie 安全設計
- 相關專題:登出與 Session 管理
- OWASP Authentication Cheat Sheet:Reauthentication After Risk Events
- OWASP Session Management Cheat Sheet
- OWASP Multifactor Authentication Cheat Sheet
- NIST SP 800-63B:Authentication and Lifecycle Management