feat(01-03): configure rate limiting and CSRF protection
- Add slowapi limiter with 100/minute default limit - Create CsrfSettings Pydantic model for fastapi-csrf-protect - Add deps.py with get_db re-export and validate_csrf dependency - Configure secure cookie settings (httponly, samesite=lax)
This commit is contained in:
parent
389fae97f8
commit
81486fc4f8
2 changed files with 67 additions and 0 deletions
41
backend/app/api/deps.py
Normal file
41
backend/app/api/deps.py
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
"""FastAPI dependency injection utilities."""
|
||||
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Depends, Request
|
||||
from fastapi_csrf_protect import CsrfProtect
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from backend.app.core.security import CsrfSettings
|
||||
from backend.app.db.session import get_db as _get_db
|
||||
|
||||
# Re-export get_db for cleaner imports in endpoints
|
||||
get_db = _get_db
|
||||
|
||||
|
||||
# Type alias for common dependency
|
||||
DbSession = Annotated[AsyncSession, Depends(get_db)]
|
||||
|
||||
|
||||
@CsrfProtect.load_config
|
||||
def get_csrf_config() -> CsrfSettings:
|
||||
"""Load CSRF configuration for fastapi-csrf-protect."""
|
||||
return CsrfSettings()
|
||||
|
||||
|
||||
async def validate_csrf(
|
||||
request: Request,
|
||||
csrf_protect: CsrfProtect = Depends(),
|
||||
) -> None:
|
||||
"""Validate CSRF token for state-changing requests.
|
||||
|
||||
Use as dependency on POST/PUT/DELETE endpoints that need CSRF protection:
|
||||
|
||||
@router.post("/items")
|
||||
async def create_item(
|
||||
_: None = Depends(validate_csrf),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
...
|
||||
"""
|
||||
await csrf_protect.validate_csrf(request)
|
||||
26
backend/app/core/security.py
Normal file
26
backend/app/core/security.py
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
"""Security configuration for rate limiting and CSRF protection."""
|
||||
|
||||
from pydantic import BaseModel
|
||||
from slowapi import Limiter
|
||||
from slowapi.util import get_remote_address
|
||||
|
||||
from backend.app.core.config import settings
|
||||
|
||||
# Rate limiter configuration
|
||||
# See: 01-RESEARCH.md Pattern 3: FastAPI Security Middleware Stack
|
||||
limiter = Limiter(
|
||||
key_func=get_remote_address,
|
||||
default_limits=["100/minute"],
|
||||
# For production, use Redis: storage_uri="redis://localhost:6379"
|
||||
# For development, uses in-memory storage by default
|
||||
)
|
||||
|
||||
|
||||
class CsrfSettings(BaseModel):
|
||||
"""CSRF protection settings for fastapi-csrf-protect."""
|
||||
|
||||
secret_key: str = settings.csrf_secret_key
|
||||
cookie_samesite: str = "lax"
|
||||
cookie_secure: bool = True # HTTPS only
|
||||
cookie_httponly: bool = True
|
||||
cookie_domain: str = settings.cookie_domain
|
||||
Loading…
Add table
Reference in a new issue