59 lines
2.4 KiB
Python
59 lines
2.4 KiB
Python
# app/core/auth.py
|
|
from fastapi import Depends, HTTPException, status, Request
|
|
from fastapi.security import HTTPBasic, HTTPBasicCredentials
|
|
from typing import Dict, Optional, Any
|
|
import secrets
|
|
import logging
|
|
from app.core.config import get_settings
|
|
|
|
logger = logging.getLogger('VADApp')
|
|
|
|
# Базовая HTTP аутентификация
|
|
security = HTTPBasic()
|
|
|
|
# Хранилище сессий (в реальном приложении лучше использовать Redis или другое хранилище)
|
|
sessions: Dict[str, str] = {}
|
|
|
|
def verify_credentials(credentials: HTTPBasicCredentials) -> bool:
|
|
"""Проверка учетных данных пользователя"""
|
|
settings = get_settings()
|
|
correct_username = settings.auth.username
|
|
correct_password = settings.auth.password
|
|
|
|
# Безопасное сравнение строк для предотвращения timing-атак
|
|
is_username_correct = secrets.compare_digest(credentials.username, correct_username)
|
|
is_password_correct = secrets.compare_digest(credentials.password, correct_password)
|
|
|
|
return is_username_correct and is_password_correct
|
|
|
|
def create_session_token(username: str) -> str:
|
|
"""Создание токена сессии"""
|
|
token = secrets.token_hex(16)
|
|
sessions[token] = username
|
|
logger.info(f"Создана новая сессия для пользователя {username}")
|
|
return token
|
|
|
|
def remove_session(token: str) -> None:
|
|
"""Удаление сессии"""
|
|
if token in sessions:
|
|
username = sessions.pop(token)
|
|
logger.info(f"Сессия для пользователя {username} удалена")
|
|
|
|
def get_current_user(request: Request) -> Optional[str]:
|
|
"""Получение текущего пользователя из сессии"""
|
|
token = request.cookies.get("session_token")
|
|
if token and token in sessions:
|
|
return sessions[token]
|
|
return None
|
|
|
|
def require_auth(request: Request) -> str:
|
|
"""Проверка аутентификации пользователя"""
|
|
username = get_current_user(request)
|
|
if not username:
|
|
logger.warning("Попытка доступа без аутентификации")
|
|
raise HTTPException(
|
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
detail="Требуется аутентификация",
|
|
headers={"WWW-Authenticate": "Basic"},
|
|
)
|
|
return username |