Spaces:
Running
Running
superxuu commited on
Commit ·
d36190a
1
Parent(s): f3f02a5
feat: add rate limiting to register and login endpoints (10/sec)
Browse files- backend/app/api.py +5 -2
- backend/app/limiter.py +6 -0
- backend/app/main.py +8 -0
- backend/requirements.txt +1 -0
backend/app/api.py
CHANGED
|
@@ -36,6 +36,7 @@ from .database_user import (
|
|
| 36 |
match_pending_payment_order,
|
| 37 |
register_user,
|
| 38 |
)
|
|
|
|
| 39 |
|
| 40 |
VMQ_GATEWAY_URL = os.getenv("VMQ_GATEWAY_URL", "")
|
| 41 |
|
|
@@ -177,7 +178,8 @@ async def health_check():
|
|
| 177 |
|
| 178 |
|
| 179 |
@router.post("/v1/auth/register", response_model=AuthResponse)
|
| 180 |
-
|
|
|
|
| 181 |
username = payload.username.strip()
|
| 182 |
if len(username) < 3 or len(payload.password) < 6:
|
| 183 |
raise HTTPException(status_code=400, detail="用户名至少3位,密码至少6位")
|
|
@@ -201,7 +203,8 @@ async def register(payload: RegisterRequest, db: Session = Depends(get_user_db))
|
|
| 201 |
|
| 202 |
|
| 203 |
@router.post("/v1/auth/login", response_model=AuthResponse)
|
| 204 |
-
|
|
|
|
| 205 |
user = db.query(User).filter(User.username == payload.username.strip()).first()
|
| 206 |
if not user or not verify_password(payload.password, user.password_hash):
|
| 207 |
raise HTTPException(status_code=401, detail="用户名或密码错误")
|
|
|
|
| 36 |
match_pending_payment_order,
|
| 37 |
register_user,
|
| 38 |
)
|
| 39 |
+
from .limiter import limiter
|
| 40 |
|
| 41 |
VMQ_GATEWAY_URL = os.getenv("VMQ_GATEWAY_URL", "")
|
| 42 |
|
|
|
|
| 178 |
|
| 179 |
|
| 180 |
@router.post("/v1/auth/register", response_model=AuthResponse)
|
| 181 |
+
@limiter.limit("10/second")
|
| 182 |
+
async def register(request: Request, payload: RegisterRequest, db: Session = Depends(get_user_db)):
|
| 183 |
username = payload.username.strip()
|
| 184 |
if len(username) < 3 or len(payload.password) < 6:
|
| 185 |
raise HTTPException(status_code=400, detail="用户名至少3位,密码至少6位")
|
|
|
|
| 203 |
|
| 204 |
|
| 205 |
@router.post("/v1/auth/login", response_model=AuthResponse)
|
| 206 |
+
@limiter.limit("10/second")
|
| 207 |
+
async def login(request: Request, payload: LoginRequest, db: Session = Depends(get_user_db)):
|
| 208 |
user = db.query(User).filter(User.username == payload.username.strip()).first()
|
| 209 |
if not user or not verify_password(payload.password, user.password_hash):
|
| 210 |
raise HTTPException(status_code=401, detail="用户名或密码错误")
|
backend/app/limiter.py
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from slowapi import Limiter
|
| 2 |
+
from slowapi.util import get_remote_address
|
| 3 |
+
|
| 4 |
+
# 创建全局限制器
|
| 5 |
+
# 使用远程 IP 作为限制标识
|
| 6 |
+
limiter = Limiter(key_func=get_remote_address)
|
backend/app/main.py
CHANGED
|
@@ -10,6 +10,10 @@ from contextlib import asynccontextmanager
|
|
| 10 |
from fastapi import FastAPI
|
| 11 |
from fastapi.staticfiles import StaticFiles
|
| 12 |
from fastapi.middleware.cors import CORSMiddleware
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
|
| 14 |
from .api import router
|
| 15 |
from .database import get_db
|
|
@@ -78,6 +82,10 @@ app = FastAPI(
|
|
| 78 |
lifespan=lifespan
|
| 79 |
)
|
| 80 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
# CORS 配置
|
| 82 |
app.add_middleware(
|
| 83 |
CORSMiddleware,
|
|
|
|
| 10 |
from fastapi import FastAPI
|
| 11 |
from fastapi.staticfiles import StaticFiles
|
| 12 |
from fastapi.middleware.cors import CORSMiddleware
|
| 13 |
+
from slowapi.errors import RateLimitExceeded
|
| 14 |
+
from slowapi import _rate_limit_exceeded_handler
|
| 15 |
+
|
| 16 |
+
from .limiter import limiter
|
| 17 |
|
| 18 |
from .api import router
|
| 19 |
from .database import get_db
|
|
|
|
| 82 |
lifespan=lifespan
|
| 83 |
)
|
| 84 |
|
| 85 |
+
# 注册限制器
|
| 86 |
+
app.state.limiter = limiter
|
| 87 |
+
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
|
| 88 |
+
|
| 89 |
# CORS 配置
|
| 90 |
app.add_middleware(
|
| 91 |
CORSMiddleware,
|
backend/requirements.txt
CHANGED
|
@@ -10,4 +10,5 @@ yfinance>=0.2.36
|
|
| 10 |
apscheduler>=3.10.4
|
| 11 |
pytz>=2024.1
|
| 12 |
sqlalchemy>=2.0.35
|
|
|
|
| 13 |
|
|
|
|
| 10 |
apscheduler>=3.10.4
|
| 11 |
pytz>=2024.1
|
| 12 |
sqlalchemy>=2.0.35
|
| 13 |
+
slowapi>=0.1.9
|
| 14 |
|