Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Аутентификация (Authentication)
Аутентификация — это процесс проверки подлинности пользователя. Система убеждается, что пользователь действительно тот, за кого себя выдаёт. Ответ на вопрос: "Ты кто?"
Аутентификация vs Авторизация
Эти два термина часто путают:
- Аутентификация — кто ты? (Identity: "я Alice")
- Авторизация — что ты можешь делать? (Permissions: "Alice может редактировать посты")
# Пример: проверка доступа
1. Аутентификация → login("alice", "password123") → Хорошо! Ты Alice
2. Авторизация → can_edit_post(alice, post_id) → Да, Alice может редактировать
Методы аутентификации
1. Basic Authentication (логин + пароль)
# Самый простой метод
from fastapi import FastAPI, HTTPException, Depends
from fastapi.security import HTTPBasic, HTTPBasicCredentials
import hashlib
app = FastAPI()
security = HTTPBasic()
# База пользователей (в реальной жизни — БД)
USERS = {
"alice": "hashed_password_123",
"bob": "hashed_password_456"
}
def hash_password(password: str) -> str:
"""Хэширование пароля (используй bcrypt в продакшене!)"""
return hashlib.sha256(password.encode()).hexdigest()
@app.get("/protected")
def protected_route(credentials: HTTPBasicCredentials = Depends(security)):
"""Защищённый эндпойнт"""
# Проверяем пользователя
hashed = hash_password(credentials.password)
if credentials.username not in USERS or USERS[credentials.username] != hashed:
raise HTTPException(status_code=401, detail="Invalid credentials")
return {"message": f"Hello, {credentials.username}!"}
2. Token-Based Authentication (JWT)
from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import HTTPBearer, HTTPAuthCredentials
from datetime import datetime, timedelta, UTC
import jwt
app = FastAPI()
security = HTTPBearer()
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
TOKEN_EXPIRE = timedelta(hours=1)
def create_token(user_id: str) -> str:
"""Создание JWT токена"""
payload = {
"user_id": user_id,
"exp": datetime.now(UTC) + TOKEN_EXPIRE,
"iat": datetime.now(UTC)
}
return jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
@app.post("/login")
def login(username: str, password: str):
"""Вход — выдача токена"""
# Проверка учётных данных
if not verify_credentials(username, password):
raise HTTPException(status_code=401, detail="Invalid credentials")
token = create_token(username)
return {"access_token": token, "token_type": "bearer"}
def verify_token(credentials: HTTPAuthCredentials = Depends(security)):
"""Проверка токена в защищённых эндпойнтах"""
try:
payload = jwt.decode(credentials.credentials, SECRET_KEY, algorithms=[ALGORITHM])
user_id = payload.get("user_id")
if not user_id:
raise HTTPException(status_code=401, detail="Invalid token")
return user_id
except jwt.ExpiredSignatureError:
raise HTTPException(status_code=401, detail="Token expired")
except jwt.DecodeError:
raise HTTPException(status_code=401, detail="Invalid token")
@app.get("/me")
def get_user(user_id: str = Depends(verify_token)):
"""Получить текущего пользователя"""
return {"user_id": user_id, "message": "Your protected data"}
3. OAuth 2.0 (делегированная аутентификация)
# Вход через Google, GitHub, Facebook и т.д.
# Пользователь НЕ передаёт пароль вашему приложению
from fastapi import FastAPI
from authlib.integrations.starlette_client import OAuth
app = FastAPI()
oauth = OAuth()
oauth.register(
name="google",
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
server_metadata_url="https://accounts.google.com/.well-known/openid-configuration",
client_kwargs={"scope": "openid email profile"}
)
@app.get("/auth/login")
async def login(request):
"""Редирект на Google для аутентификации"""
redirect_uri = request.url_for("auth")
return await oauth.google.authorize_redirect(request, redirect_uri)
@app.get("/auth/callback")
async def auth(request):
"""Callback после успешной аутентификации в Google"""
token = await oauth.google.authorize_access_token(request)
user_info = token["userinfo"]
return {"user": user_info}
4. Multi-Factor Authentication (MFA)
# Двухфакторная аутентификация: пароль + код из SMS/приложения
def authenticate_with_mfa(username: str, password: str, totp_code: str):
"""Аутентификация с двумя факторами"""
# Шаг 1: Проверка пароля
if not verify_password(username, password):
raise Exception("Invalid password")
# Шаг 2: Проверка TOTP кода (Time-based One-Time Password)
user = get_user(username)
if not verify_totp(user.totp_secret, totp_code):
raise Exception("Invalid TOTP code")
# Оба фактора верны — аутентификация успешна
return create_token(username)
Процесс аутентификации: пошагово
1. Пользователь вводит логин и пароль
↓
2. Приложение отправляет на сервер
↓
3. Сервер проверяет учётные данные в БД
↓
4. Пароль совпадает → выдаёт токен/сессию
↓
5. Клиент сохраняет токен
↓
6. При каждом запросе отправляет токен в заголовке Authorization
↓
7. Сервер проверяет токен → разрешает доступ
Безопасность паролей
# ❌ Неправильно — хранить пароль в открытом виде
USERS = {"alice": "password123"}
# ✅ Правильно — использовать хеширование
from bcrypt import hashpw, gensalt, checkpw
hashed = hashpw("password123".encode(), gensalt())
# $2b$12$abcdef...
# Проверка при входе
if checkpw("password123".encode(), hashed):
print("Password correct!")
Сессии vs Токены
| Параметр | Сессия | Токен (JWT) |
|---|---|---|
| Где хранить | На сервере | На клиенте |
| Масштабируемость | Сложно (нужна синхронизация) | Легко (stateless) |
| Память сервера | Требуется | Не требуется |
| Скорость | Медленнее (поиск в БД) | Быстрее (валидация подписи) |
| Отзыв | Немедленный | Только до истечения срока |
Ключевые моменты
- Аутентификация = проверка подлинности (кто ты?)
- Пароли ВСЕГДА хешируются (bcrypt, argon2)
- JWT токены — stateless и масштабируемы
- Refresh Token — для обновления доступа
- HTTPS обязателен — для передачи учётных данных
- MFA — дополнительный уровень безопасности
- OAuth 2.0 — безопасная делегированная аутентификация