/
olevok
/
python-dev-course
Обзор
Документация
Войти
/
olevok
/
python-dev-course
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
Part 8 - FastAPI/L16/L16_2/main.py
188 строк
7 KB
PetrovSerega
Update L16
20 июн 2026, 17:53
20 июн 2026, 17:53
285f51f
Код
Авторство
О чём код?
# uvicorn L16_2.main:app --reload from fastapi import FastAPI, Depends, HTTPException from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials from typing import Annotated app = FastAPI() # Создаем схему безопасности auth_scheme = HTTPBearer() # region Основы аутентификации и авторизации. Пример 1: Проверка наличия Bearer Token @app.get("/get_info") def get_info(token: HTTPAuthorizationCredentials = Depends(auth_scheme)): # FastAPI сам проверил наличие заголовка Authorization: Bearer ... # Если его нет, эндпоинт вернет 403 Forbidden автоматически return { "message": "Вы успешно прошли аутентификацию!", "token_received": token.credentials, # сам текст токена } # endregion # region Основы аутентификации и авторизации. Пример 2: Проверка значения Bearer Token # Зависимость для проверки значения токена def verify_token( credentials: Annotated[HTTPAuthorizationCredentials, Depends(auth_scheme)], ): token = credentials.credentials if token != "super-secret-key": raise HTTPException(status_code=401, detail="Неверный или просроченный токен") return token @app.get("/admin") def admin(token: Annotated[str, Depends(verify_token)]): return {"status": "success", "data": "Секретные данные для админа"} @app.get("/public") def public(): return {"message": "Эти данные видны всем"} # endregion # region Основы аутентификации и авторизации. Пример 3: Глобальная зависимость # Для всех методов будет проверяться токен # app = FastAPI(dependencies=[Depends(verify_token)]) # @app.get("/admin") # def admin(): # return {"status": "success", "data": "Секретные данные для админа"} # @app.get("/public") # def public(): # return {"message": "Эти данные видны всем"} # endregion # region Создание зависимости get_current_user. Пример 1: Зависимость get_current_user from pydantic import BaseModel class User(BaseModel): id: int username: str # Имитация базы данных пользователей (токен -> пользователь) users_db = { "token-alice": User(id=1, username="alice"), "token-bob": User(id=2, username="bob"), } def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(auth_scheme)): token = credentials.credentials user = users_db.get(token) if not user: raise HTTPException(status_code=401, detail="Неверный токен пользователя") return user @app.get("/profile") def profile(current_user: User = Depends(get_current_user)): return {"user": current_user} # endregion # region Создание зависимости get_current_user. Пример 1: Зависимость get_current_user + проверка роли # Добавляем роль пользователя class UserWithRole(BaseModel): id: int username: str role: str # Добавляем роли пользователям users_with_roles_db = { "token-alice": UserWithRole(id=1, username="alice", role="admin"), "token-bob": UserWithRole(id=2, username="bob", role="employee"), "token-john": UserWithRole(id=3, username="john", role=""), } # Базовая зависимость -> получаем текущего пользователя (меняется только источник данных) def get_current_user_with_role( credentials: HTTPAuthorizationCredentials = Depends(auth_scheme), ): token = credentials.credentials user = users_with_roles_db.get(token) if not user: raise HTTPException(status_code=401, detail="Неверный токен пользователя") return user # Класс-зависимость для проверки роли class RoleChecker: def __init__(self, allowed_roles: list[str]): self.allowed_roles = allowed_roles def __call__(self, user: Annotated[User, Depends(get_current_user_with_role)]): if user.role not in self.allowed_roles: raise HTTPException( status_code=403, detail="У вас недостаточно прав для выполнения этой операции", ) return user # Эндпоинт доступен всем авторизованным @app.get("/user_data") def user_data(user: Annotated[User, Depends(get_current_user_with_role)]): return {"status": "success", "data": "Данные для всех авторизованных пользователей"} # Эндпоинт доступен и админам, и обычным сотрудникам @app.get("/employee_data") def employee_data(user: Annotated[User, Depends(RoleChecker(["admin", "employee"]))]): return {"status": "success", "data": "Данные для всех сотрудников"} # Эндпоинт доступен только админам @app.get("/admin_data") def admin_data(user: Annotated[User, Depends(RoleChecker(["admin"]))]): return {"status": "success", "data": "Секретные данные для админа"} # endregion # region Аутентификация через Логин и Пароль, хеширование. Пример 1: Вход по логину и паролю from fastapi.security import OAuth2PasswordRequestForm @app.post("/login") def login(form_data: OAuth2PasswordRequestForm = Depends()): # ЦЕПОЧКА АУТЕНТИФИКАЦИИ: # 1. КЛИЕНТ -> Отправляет ЛОГИН/ПАРОЛЬ через форму (OAuth2PasswordRequestForm) # 2. СЕРВЕР -> Получает пароль, ХЭШИРУЕТ его и сравнивает с ХЭШЕМ в базе данных # 3. СЕРВЕР -> Если хэши совпали, генерирует и возвращает ТОКЕН (access_token) # 4. КЛИЕНТ -> Сохраняет токен и ПРИКРЕПЛЯЕТ его к каждому следующему запросу # 5. СЕРВЕР -> Теперь проверяет только ТОКЕН (через Depends), не спрашивая пароль снова if form_data.username == "alice" and form_data.password == "123456": return {"access_token": "token-alice", "token_type": "bearer"} raise HTTPException(status_code=401, detail="Неверный логин или пароль") # endregion