跳至主要內容
Skip to content

高風險操作重新驗證

很多登入系統會犯一個錯:

text
使用者已經登入了,所以所有操作都可以直接做。

這在一般瀏覽頁面可能沒問題。

但如果操作變成:

  • 修改密碼。
  • 修改手機號碼。
  • 新增收款帳號。
  • 匯出個資。
  • 查看醫療資料。
  • 申請政府服務。
  • 停用 MFA。
  • 綁定新的第三方登入。
  • 執行管理員高權限操作。

那只靠「目前 session 還有效」通常不夠。

原因很簡單:

text
Session 有可能被劫持。
電腦有可能暫時離開本人控制。
登入可能發生在很久以前。
目前操作的風險可能高於原本登入時的風險。

所以高風險操作常需要重新驗證,也就是:

text
Step-up Authentication / Reauthentication

這篇要回答:

  • 什麼是高風險操作重新驗證?
  • 它和一般登入、MFA、數位簽章差在哪?
  • 哪些操作應該觸發重新驗證?
  • 重新驗證後要不要重新建立 session?
  • Step-up token 怎麼設計?
  • 前後端流程怎麼做才不會變成安全假象?

一、 一句話回答

如果面試官問:

高風險操作為什麼要重新驗證?怎麼設計?

可以先回答:

已登入只代表目前 session 曾經通過身份驗證,不代表使用者現在仍在控制該 session,也不代表這個 session 足以執行所有敏感操作。高風險操作重新驗證是在使用者執行修改密碼、修改 MFA、變更收款帳號、查看敏感資料、提交申請等操作前,要求使用者再用密碼、MFA、Passkey、TW FidO 或其他高強度方式確認身份。驗證通過後,系統可以發一個短效、單用途、綁定操作的 step-up token,並記錄 audit log;但它仍不等於數位簽章,若要表示對文件或交易內容承諾,還需要額外簽章流程。

短一點可以說:

text
重新驗證是確認「現在這個人仍然有權做這個敏感操作」。

二、 重新驗證解決什麼問題

登入和 session 解決的是:

text
這個使用者曾經通過驗證,系統可以在一段時間內識別他。

但高風險操作還需要問:

text
這個操作夠敏感嗎?
現在是否仍然是本人?
目前登入強度夠嗎?
這次操作是否需要更強證據?

重新驗證可以降低幾種風險:

風險說明
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。

例如:

text
修改密碼前要求再輸入目前密碼
新增收款帳號前要求 TOTP
匯出醫療資料前要求 TW FidO
管理員刪除使用者前要求 Passkey

但重新驗證本身不是數位簽章。

它通常只代表:

text
這次敏感操作前,系統重新確認了操作者身份。

如果要代表:

text
使用者簽署某份申請書或合約。

那還要回到前一篇的數位簽章設計。

四、 哪些操作應該要求重新驗證

可以用一個簡單準則:

text
如果這個操作一旦被攻擊者執行,會造成帳號接管、金錢損失、個資外洩、法律效果或不可逆影響,就應該考慮重新驗證。

常見類別如下。

1. 帳號安全設定

  • 修改密碼。
  • 修改 Email。
  • 修改手機。
  • 啟用 / 停用 MFA。
  • 產生 backup codes。
  • 新增 Passkey。
  • 刪除 Passkey。
  • 新增可信裝置。
  • 查看或重設 recovery key。

這類操作直接影響帳號控制權。

如果攻擊者拿到 session,第一件事通常就是改掉恢復方式或停用 MFA。

2. 金流與交易

  • 新增收款帳號。
  • 修改付款方式。
  • 提款。
  • 大額轉帳。
  • 建立定期扣款。
  • 修改發票或稅務資訊。

金流場景通常不只需要重新驗證,某些情況還需要交易簽章或額外風控。

3. 個資與敏感資料

  • 查看完整身分證字號。
  • 查看醫療紀錄。
  • 匯出大量個資。
  • 下載報表。
  • 查看 API key。
  • 查看金鑰或 webhook secret。

這類操作的風險是資料外洩。

即使攻擊者不能改資料,只要能看資料也可能造成嚴重損害。

4. 政府、醫療、金融申辦

  • 送出線上申請。
  • 查詢健保或醫療資料。
  • 授權代理人。
  • 修改戶籍、稅務、保險相關資料。
  • 提交具有法律效果的表單。

這類操作通常要分清楚:

text
重新驗證
數位簽章
授權資格檢查

它們可能都需要,但不是同一件事。

5. 後台高權限操作

  • 修改使用者角色。
  • 新增管理員。
  • 刪除資料。
  • 匯出客戶名單。
  • 調整安全設定。
  • 產生 production token。
  • 修改金流或通知設定。

後台系統尤其需要 step-up authentication,因為一個管理員 session 被劫持,影響面可能是全站。

五、 什麼時候觸發重新驗證

重新驗證不只看操作類型,也可以看情境。

觸發條件例子
操作敏感修改密碼、匯出資料、提款
距離上次驗證太久登入超過 30 分鐘後才修改安全設定
session 閒置太久使用者長時間沒操作
裝置異常新裝置、新瀏覽器、裝置指紋變化
網路異常IP 國家變更、VPN、Tor、資料中心 IP
行為異常短時間大量操作、速度不像人類
權限異常嘗試使用不常用的管理功能
帳號狀態改變剛重設密碼、剛恢復帳號

這就是 risk-based authentication 的延伸。

不要把所有功能都做成每一步都要重新驗證。

比較好的體驗是:

text
普通操作不打擾
敏感操作才提高驗證強度
風險越高,驗證越強

六、 Step-up Authentication 流程

典型流程:

重點是:

text
敏感 API 自己要檢查重新驗證狀態,
不能只靠前端是否顯示了重新驗證畫面。

前端只是體驗。

後端才是安全邊界。

七、 Step-up Token 怎麼設計

重新驗證通過後,可以發一個短效授權。

它可以是 server-side grant,也可以是短效 token。

概念:

ts
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方便追查

不要發一個通用的:

text
reauthenticated=true,有效一天。

這樣會讓重新驗證失去精準性。

八、 要不要旋轉 Session

OWASP 對高風險事件後的重新驗證,建議搭配安全 session 管理,例如重新驗證後旋轉 token 或 session id。

實務上可以分兩種場景。

1. 普通 step-up 操作

例如:

text
查看完整手機號碼
下載一份報表

可以只發短效 step-up grant,不一定要重建整個 session。

2. 帳號安全狀態變更

例如:

text
修改密碼
停用 MFA
新增 Passkey
重設 recovery key

這類操作會改變帳號安全狀態,建議:

  • 重新驗證。
  • 旋轉目前 session id。
  • 撤銷其他裝置 session。
  • 撤銷 refresh token。
  • 發送安全通知。
  • 記錄 audit log。

尤其是修改密碼後,通常應提供:

text
登出其他所有裝置

或者依風險直接強制撤銷其他 session。

九、 驗證方式怎麼選

不是所有操作都需要同一種驗證方式。

可以依風險分層:

風險操作建議重新驗證
查看一般資料不需要,或只檢查 session 新鮮度
修改暱稱、地址密碼或已登入 session + recent auth
修改手機、停用 MFA密碼 + MFA / Passkey
很高大額交易、政府申辦、醫療授權高強度 MFA、TW FidO、自然人憑證、交易簽章
管理員高風險刪除資料、新增 adminPasskey / MFA + 操作審核 + audit log

常見方法:

  • 輸入目前密碼。
  • Email OTP。
  • SMS OTP。
  • TOTP。
  • Backup code。
  • Passkey / WebAuthn。
  • TW FidO。
  • 自然人憑證。

但要注意:

text
重新輸入密碼不是萬能。

如果攻擊者本來就是用密碼登入,修改 MFA 前只要求同一組密碼,保護效果有限。

對高風險操作,更好的方式通常是:

text
不同因素 + 更強抗釣魚能力。

例如 Passkey、硬體金鑰、TW FidO 或 TOTP,會比只要求再輸入密碼更好。

十、 Recent Authentication

很多系統不會每次都要求完整重新驗證,而是看:

text
使用者是否在最近一段時間內完成過高強度驗證。

例如:

ts
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 分鐘
修改手機 / Email5 分鐘
停用 MFA每次都重新驗證
大額交易每筆交易都要 step-up 或簽章
管理員刪除資料每次都重新驗證

這樣可以平衡安全與體驗。

但要避免:

text
使用者剛登入一次,接下來 24 小時所有敏感操作都不用重新驗證。

時間窗越長,風險越高。

十一、 後端 API 要怎麼檢查

前端可以顯示重新驗證 modal,但後端一定要強制檢查。

錯誤:

ts
// 只靠前端控制按鈕
if (uiState.reauthenticated) {
  showChangePasswordButton()
}

正確:

ts
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追蹤用

資料表概念:

sql
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。
  • 新增收款帳號。
  • 管理員權限已變更。

通知內容不要洩漏敏感資料,但要讓使用者能快速發現異常。

十三、 使用者體驗怎麼設計

重新驗證不能做得像懲罰使用者。

好的體驗是:

text
只有在必要時出現,
清楚說明正在保護哪個操作,
驗證完成後回到原本流程。

例如:

text
為了保護你的帳號,修改手機號碼前需要再次確認身份。

不要寫:

text
錯誤,請重新登入。

重新驗證完成後應該:

  • 保留使用者已填寫內容。
  • 回到原本操作。
  • 不要讓使用者重新走整個流程。
  • 錯誤訊息不要透露太多安全細節。
  • 支援合理的備援方式。

如果驗證失敗多次:

  • 限制重試。
  • 提高風險分數。
  • 發送安全通知。
  • 必要時暫停敏感操作。

十四、 和 CSRF、XSS 的關係

重新驗證不是 CSRF 或 XSS 的替代品。

它只是多一道保護。

敏感操作仍要有:

  • CSRF 防護。
  • SameSite cookie。
  • HttpOnly cookie。
  • XSS 防護。
  • rate limit。
  • idempotency key。
  • 權限檢查。

例如 CSRF 攻擊可能誘導使用者送出請求。

如果敏感 API 要求 step-up token,而且 token 不是攻擊者能取得的,攻擊難度會提高。

但如果網站有 XSS,攻擊者可能在使用者完成重新驗證後偷走可用 token。

所以重新驗證不能單獨存在。

十五、 和數位簽章的界線

重新驗證回答:

text
這次敏感操作前,系統再次確認了操作者身份。

數位簽章回答:

text
這個人對特定內容留下可驗證簽署證據。

例如:

text
修改手機號碼

通常重新驗證即可。

但:

text
簽署線上申請書
大額轉帳
同意醫療授權
提交具法律效果文件

可能需要重新驗證加上交易簽章或數位簽章。

可以這樣判斷:

需求應該用
確認目前仍是本人操作重新驗證
提高某個操作的登入強度Step-up authentication
記錄誰做了敏感操作Audit log
對特定文件或交易留下可驗證承諾數位簽章 / 交易簽章

十六、 常見錯誤

1. 所有敏感操作只靠登入狀態

錯誤:

text
只要 session 有效,就可以修改密碼和停用 MFA。

正確:

text
高風險操作要檢查 recent auth 或要求重新驗證。

2. 只在前端做重新驗證

錯誤:

text
前端顯示 modal,通過後才打 API。

正確:

text
後端 API 必須驗證 step-up grant。

3. Step-up token 太通用

錯誤:

text
reauthenticated=true,有效 24 小時。

正確:

text
短效、單用途、綁定 session、綁定操作。

4. 修改安全設定後不撤銷其他 session

錯誤:

text
密碼改完,但舊裝置仍全部在線。

正確:

text
視風險撤銷其他 session / refresh token,並通知使用者。

5. 把重新驗證當成簽章

錯誤:

text
送出申請前有重新驗證,所以等同簽署申請書。

正確:

text
重新驗證只是確認身份;簽章要對特定內容產生可驗證證據。

6. 驗證方式和風險不匹配

錯誤:

text
停用 MFA 只要求 Email OTP。

正確:

text
高風險安全設定應要求更強因素,例如目前密碼 + 已啟用 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、裝置、地點、行為風險決定。驗證完成後應回到原流程,保留使用者已填內容。

十八、 實作題

題目一:設計修改手機號碼流程

好的流程:

  1. 使用者已登入。
  2. 進入修改手機頁。
  3. 後端判斷這是敏感操作。
  4. 若最近未完成強驗證,回傳 reauth_required
  5. 使用者完成密碼 + MFA 或 Passkey 驗證。
  6. 後端產生短效 step-up grant,purpose 為 change_phone
  7. 使用者輸入新手機。
  8. 系統對新手機送 OTP。
  9. OTP 驗證通過後更新手機。
  10. 旋轉 session 或更新安全狀態。
  11. 記錄 audit log。
  12. 通知舊手機或舊信箱。

題目二:設計停用 MFA 流程

好的答案應提到:

  • 停用 MFA 是高風險操作。
  • 不能只靠目前 session。
  • 要求強重新驗證。
  • 最好要求現有 MFA 或 backup code。
  • 停用後撤銷相關 backup codes。
  • 發送安全通知。
  • 記錄 audit log。
  • 可加入冷卻期或風險審核。

題目三:實作 API 防護

敏感 API 應該像這樣:

ts
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'
  })
}

重點:

text
不是前端說通過就通過,
而是後端針對敏感操作驗證 step-up grant。

十九、 資深視角

1. 重新驗證是操作級安全,不只是登入級安全

初階工程師常把安全停在:

text
有登入就好。

資深工程師會把操作分級:

text
普通操作
敏感操作
高風險操作
具有法律效果的操作

然後為不同操作配置不同的驗證強度、記錄、通知與補救流程。

2. 不要讓使用者替系統風險買單

如果每個按鈕都要重新驗證,使用者會疲乏。

最後他們會機械式按掉所有確認,安全反而下降。

好的設計是:

text
平常安靜,
關鍵時刻清楚且堅定。

3. Step-up grant 要像權限票券一樣嚴格

重新驗證通過後,不要只在 session 上掛一個永久旗標。

它應該更像:

text
針對某個操作、某個 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、撤銷其他裝置並通知使用者。但重新驗證不等於數位簽章,若要對文件或交易內容留下可驗證承諾,仍需要交易簽章或數位簽章流程。

延伸閱讀