diff --git a/app/api/v1/auth.py b/app/api/v1/auth.py index 1ad66ab..3c4f4bf 100644 --- a/app/api/v1/auth.py +++ b/app/api/v1/auth.py @@ -40,9 +40,9 @@ router = APIRouter(prefix="/api/v1/auth", tags=["auth"]) # 手机号登录防刷:同一设备(device_id) + 同一 IP 每小时最多的登录尝试次数(成功/失败都计)。 SMS_LOGIN_MAX_PER_HOUR = 5 -# 发码防刷:同一设备(device_id) + 同一 IP 每小时最多的发码次数。比登录略宽(发码含正常重发); +# 发码防刷:同一设备(device_id) + 同一 IP 每小时最多的发码次数。 # 堵「换手机号绕开单号 60s 冷却 / 单号每日上限」的洞 —— 那两道是单号维度,一机换号能绕开。 -SMS_SEND_MAX_PER_HOUR_PER_DEVICE = 10 +SMS_SEND_MAX_PER_HOUR_PER_DEVICE = 5 def _login_response( @@ -90,7 +90,6 @@ def jverify_login(req: JverifyLoginRequest, db: DbSession) -> TokenWithUser: "/sms/send", response_model=SmsSendResponse, summary="发送短信验证码", - dependencies=[Depends(rate_limit(10, 60, "sms-send"))], # 同 IP 每分钟≤10 次(防一 IP 刷不同号) ) def sms_send(req: SmsSendRequest, request: Request) -> SmsSendResponse: # 测试账号:不真发短信(号码非真实手机号,真发会失败/浪费),直接放行让客户端进入填码界面。 diff --git a/app/integrations/sms.py b/app/integrations/sms.py index df5bffc..6b16aac 100644 --- a/app/integrations/sms.py +++ b/app/integrations/sms.py @@ -14,7 +14,9 @@ worker / 多机时内存不共享 → 冷却、每日上限、校验都会失效 防刷三层(短信花钱 + `/sms/send` 在登录前无法 JWT 鉴权): 1. 单号 `SMS_SEND_INTERVAL_SEC` 冷却(本文件) 2. 单号每日 `SMS_DAILY_LIMIT_PER_PHONE` 条上限(本文件) - 3. 单 IP 频控(api 层 rate_limit 依赖)+ 极光控制台 IP 白名单/防轰炸(运维侧) + 3. 单设备(device_id)每小时频控(api 层 auth.sms_send 内 enforce_rate_limit)+ 极光控制台 IP 白名单/防轰炸(运维侧)。 + ⚠️ 原「单 IP 频控(rate_limit 依赖)」2026-06-26 按产品要求删除、改设备维度;但 device_id 客户端可伪造/轮换, + 脚本轮换 id 能绕过本层 → 挡脚本狂发主要靠极光控制台侧(+ 可选 nginx 限流)。 另:单码校验失败 `SMS_MAX_VERIFY_ATTEMPTS` 次即作废(防爆破),验过即作废(一次性)。 """ from __future__ import annotations diff --git a/tests/test_auth.py b/tests/test_auth.py index 6288b11..4968a73 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -77,7 +77,7 @@ def test_sms_send_too_frequent(client) -> None: def test_sms_send_device_ip_rate_limit(client, monkeypatch) -> None: """发码防刷:同一设备(device_id) + 同一 IP 每小时最多 N 次发码,超出 429。 用不同手机号(绕开单号 60s 冷却)证明限流按设备封顶 —— 堵「换号绕开单号冷却/每日上限」的洞。 - conftest 默认关限流;本用例临时打开 + 调小阈值(避开同 IP 10/分钟那道)+ 清计数隔离。""" + conftest 默认关限流;本用例临时打开 + 调小阈值便于测 + 清计数隔离。""" from app.api.v1 import auth from app.core import ratelimit