跳至主要内容

Scenario 2: 使用錯誤密碼登入失敗

User Story: US-001: 用戶登入

Given: 系統初始狀態

已註冊用戶

{
"userId": "user-001",
"email": "staff@florist.com",
"passwordHash": "$2b$12$...", // 對應密碼 "Password123!"
"name": "王小明",
"roles": ["ROLE_STAFF"],
"tenantId": "tenant-abc",
"loginFailedCount": 0
}

When: 執行操作

API 請求

POST /api/v1/auth/login HTTP/1.1
Content-Type: application/json

{
"email": "staff@florist.com",
"password": "WrongPassword", // 錯誤密碼
"rememberMe": false
}

Then: 預期結果

系統響應 (401 Unauthorized)

{
"error": "INVALID_CREDENTIALS",
"message": "Email 或密碼錯誤",
"timestamp": "2025-10-31T10:30:00Z"
}

數據庫變更

users 表更新

{
"userId": "user-001",
"loginFailedCount": 1, // 增加 1
"lastLoginAttemptAt": "2025-10-31T10:30:00Z",
"lastLoginAttemptIp": "192.168.1.100"
}

audit_logs 表新增記錄

{
"id": "log-001",
"tenantId": "tenant-abc",
"userId": "user-001",
"action": "USER_LOGIN",
"resourceType": "User",
"resourceId": "user-001",
"status": "FAILED",
"details": {
"reason": "INVALID_PASSWORD"
},
"ipAddress": "192.168.1.100",
"timestamp": "2025-10-31T10:30:00Z"
}

前端行為

  1. Toast 通知顯示「Email 或密碼錯誤」(紅色,5 秒)
  2. Email 欄位保留輸入值 (staff@florist.com)
  3. 密碼欄位清空
  4. 停留在登入頁面(不重定向)
  5. 不儲存任何 Token

邊界條件

連續失敗 5 次後帳號鎖定

第 5 次失敗請求

POST /api/v1/auth/login HTTP/1.1
Content-Type: application/json

{
"email": "staff@florist.com",
"password": "WrongPassword"
}

前提: loginFailedCount 已經是 4

響應 (423 Locked)

{
"error": "ACCOUNT_LOCKED",
"message": "帳號已被鎖定,請 15 分鐘後再試",
"lockedUntil": "2025-10-31T10:45:00Z",
"timestamp": "2025-10-31T10:30:00Z"
}

users 表更新

{
"userId": "user-001",
"loginFailedCount": 5,
"lockedUntil": "2025-10-31T10:45:00Z"
}

最後更新: 2025-10-31