1. ✓任務
  2. ✓Issue
  3. 3AI 修改
  4. 4分支
  5. 5PR
  6. 6完成

需求說明

登入失敗時提供可採取行動的錯誤訊息。 ## Acceptance criteria 錯誤訊息不洩漏帳號是否存在,並通過既有測試。 Agent-Desk-Work-Item: 8b89cb4c-36fd-4378-85a0-192564972441

驗收條件

錯誤訊息不洩漏帳號是否存在,並通過既有測試。

最近一次 Agent 執行

待核准 低風險

模型:gpt-5.6-luna
分支:尚未建立

查看完整執行紀錄

Pull Request

目前沒有關聯的 Pull Request。

AI 分析

分析摘要

將登入驗證失敗訊息改為不透露帳號或驗證細節的通用、可採取行動提示。

小型修改低風險可準備修正
預計修改
  • 將錯誤密碼時的「密碼錯誤」改為通用訊息,例如「登入失敗,請確認密碼後再試。」
  • 保留既有 HTTP 401 狀態,讓前端既有錯誤顯示流程繼續運作。
驗收方式
  • ✓使用錯誤密碼時回傳 HTTP 401,且訊息不透露帳號是否存在。
  • ✓登入表單顯示可採取行動的提示,指引使用者確認密碼後重試。
  • ✓使用正確密碼時仍成功建立 session 並依 next 路徑導向。
風險原因
  • 僅修改登入 API 在認證失敗時回傳的訊息,不改變驗證、session cookie 或導向流程。
  • 訊息不包含帳號是否存在等可用於帳號枚舉的資訊。
程式碼證據
apps/web/app/api/auth/login/route.ts:9-9已由 Worker 驗證
if (!body?.password || !equal(body.password, expectedPassword)) return failure("密碼錯誤", 401);

目前認證失敗訊息直接描述密碼錯誤,需要改為不洩漏驗證細節的通用提示。

apps/web/components/login-form.tsx:19-19引用無法驗證
if (!response.ok) throw new Error(body.error ?? "登入失敗");

前端會直接顯示 API 回傳的 error,因此 API 的通用訊息可被既有登入表單使用。

相關檔案
apps/web/app/api/auth/login/route.tsapps/web/components/login-form.tsx

程式碼修改

diff --git a/apps/web/app/api/auth/login/route.ts b/apps/web/app/api/auth/login/route.ts
index 60460e1..6c5cfa4 100644
--- a/apps/web/app/api/auth/login/route.ts
+++ b/apps/web/app/api/auth/login/route.ts
@@ -6,7 +6,7 @@ export async function POST(request: Request) {
const sessionSecret = process.env.DASHBOARD_SESSION_SECRET;
if (!expectedPassword || !sessionSecret) return failure("Dashboard login is not configured", 503);
const body = await request.json().catch(() => null) as { password?: string; next?: string } | null;
− if (!body?.password || !equal(body.password, expectedPassword)) return failure("密碼錯誤", 401);
+ if (!body?.password || !equal(body.password, expectedPassword)) return failure("登入失敗,請確認密碼後再試。", 401);
const next = body.next?.startsWith("/") && !body.next.startsWith("//") ? body.next : "/";
const response = ok({ authenticated: true, next });
response.cookies.set("dashboard_session", sessionSecret, { httpOnly: true, secure: process.env.NODE_ENV === "production", sameSite: "lax", path: "/", maxAge: 60 * 60 * 12 });

測試結果

最終檢查已通過,沒有失敗紀錄。