87 lines
2.6 KiB
Markdown
87 lines
2.6 KiB
Markdown
# Безопасность
|
|
|
|
## Базовые требования
|
|
|
|
- `.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)
|