# Безопасность ## Базовые требования - `.env` — всегда в `.gitignore`. Никогда не коммитить. - JWT: алгоритм HS256, access_token = 60 минут, refresh_token = 30 дней - Пароли: bcrypt через passlib - Pydantic валидация на всех входах - RBAC: роли user, admin --- ## Аутентификация ### JWT ```python # app/core/security.py def create_access_token(data: dict, expires_delta: timedelta | None = None) -> str: to_encode = data.copy() expire = datetime.now(timezone.utc) + (expires_delta or timedelta(minutes=60)) to_encode.update({"exp": expire, "type": "access"}) return jwt.encode(to_encode, settings.jwt_secret_key, algorithm=settings.jwt_algorithm) def decode_token(token: str) -> dict[str, Any] | None: try: return jwt.decode(token, settings.jwt_secret_key, algorithms=[settings.jwt_algorithm]) except JWTError: return None ``` ### Password hashing ```python from passlib.context import CryptContext pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") def hash_password(password: str) -> str: return pwd_context.hash(password) def verify_password(plain: str, hashed: str) -> bool: return pwd_context.verify(plain, hashed) ``` --- ## RBAC | Роль | Права | |------|-------| | user | Базовые: CRUD своих данных, запуск анализа | | admin (is_superuser) | Управление пользователями, просмотр логов, системные настройки | Проверка прав: ```python async def require_admin(user: Annotated[User, Depends(get_current_user)]) -> User: if not user.is_superuser: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Admin access required") return user ``` --- ## Sensitive Data **Никогда не логировать:** - Пароли (даже хэш) - JWT токены - API keys и секреты - Email в открытом виде (только user_id) **Маскировать в логах:** - Email: u***@mail.ru - IP: 195.208.*.* --- ## [ASK] Вопросы по безопасности - Нужен ли audit log? (рекомендуется для production) - Нужно ли шифрование данных в покое? (да, если хранятся персональные данные) - Нужен ли rate limiting? (да, для production) - Нужен ли CORS? (да, если фронтенд на другом домене) - Нужен ли CSRF? (нет, если используем JWT в Bearer header)