2a0e9255ae
- Account lockout:連續失敗 5 次鎖定 15 分鐘(Fixed Window,Cache)
- Member / Provider 各自獨立 namespace
- Email 正規化(strtolower+trim)
- 不存在帳號不累計計數(防 Cache 污染)
- companion key 記錄 locked_until(ISO 8601)
- OAuth CSRF 防護:移除 stateless(),手動 state 生成與驗證
- session('oauth_state') + session('state') 雙寫確保 Socialite 內建驗證通過
- state mismatch redirect 至 /login?error=oauth_failed
- throttle 從 5,1 調整為 10,1,避免 IP throttle 在 lockout 前觸發
- NormalizesEmail Trait、config/auth_lockout.php
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2.2 KiB
2.2 KiB
Why
IP-based throttle(P0 已實作)只能防單一 IP 暴力攻擊,無法阻擋分散式密碼暴破(攻擊者用多 IP 對同一帳號嘗試);OAuth 流程目前以 stateless() 繞過 CSRF 驗證,存在被偽造授權碼的風險。在金流整合上線前先補齊這兩個帳號層防護,可大幅降低帳號接管與 OAuth CSRF 風險。
What Changes
- 新增帳號層鎖定機制:Member / Provider 登入連續失敗 N 次後,鎖定該帳號(而非 IP),鎖定期間回傳 HTTP 423;鎖定計數以 Laravel Cache 儲存,N 分鐘後自動解鎖。
- 新增 OAuth state 驗證:
SocialAuthController產生隨機 state 字串存入 session,callback 時驗證 state 是否吻合;不吻合時拒絕並回傳 HTTP 400;移除stateless()呼叫。
Capabilities
New Capabilities
account-lockout:帳號層連續失敗鎖定,覆蓋 Member / Provider 登入流程(Admin 登入失敗計數另行討論,暫不列入)oauth-state-validation:OAuth CSRF 防護,補 state parameter 生成與驗證,適用 Member Google OAuth 流程
Modified Capabilities
login-rate-limiting:無需變更需求(IP throttle 與帳號鎖定並行,各自獨立,Requirement 不衝突)
Impact
後端
app/Http/Controllers/API/AuthController.php(Member login)app/Http/Controllers/API/ProviderAuthController.php(Provider login)app/Http/Controllers/API/SocialAuthController.php(OAuth redirect / callback)routes/api.php(可能新增解鎖端點)config/auth_lockout.php(鎖定參數:最大失敗次數、鎖定時間)- Laravel Cache(驗證失敗計數,driver 使用現有 Redis 或 file)
前端
src/views/LoginView.vue/CoachLoginView.vue:顯示「帳號已鎖定,請稍後再試」錯誤訊息(HTTP 423 對應)src/plugins/echo.js/src/api/axios.js:無需變更(OAuth callback 不走 Axios)src/views/AuthCallbackView.vue:無需變更(後端回傳 400 時 redirect 到 login 並帶錯誤訊息)
不影響
- 現有 Sanctum token、sessionStorage、refresh interceptor
- Admin Panel(Admin 登入鎖定不在此 change 範圍)