Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
HTTP Basic Authorization (Basic Auth)
Определение
Basic Authorization — это самый простой способ аутентификации в HTTP. Клиент отправляет username и password в header, закодированные в Base64.
Это НЕ шифрование, а просто кодирование для удобства передачи по HTTP.
Как работает Basic Auth
Шаг 1: Подготовка credentials
import base64
username = "user@example.com"
password = "mySecretPassword"
# Объединяем username:password
credentials = f"{username}:{password}"
# Кодируем в Base64
encoded = base64.b64encode(credentials.encode()).decode()
print(encoded) # "dXNlckBleGFtcGxlLmNvbTpteVNlY3JldFBhc3N3b3Jk"
Шаг 2: Отправка в заголовке
import requests
username = "user@example.com"
password = "mySecretPassword"
# Способ 1: Вручную с заголовком Authorization
headers = {
"Authorization": f"Basic {encoded}"
}
response = requests.get("https://api.example.com/data", headers=headers)
# Способ 2: Встроенный в requests (более удобно)
response = requests.get(
"https://api.example.com/data",
auth=(username, password) # requests автоматически кодирует
)
print(response.status_code)
Шаг 3: Сервер проверяет credentials
from fastapi import FastAPI, HTTPException, Header
import base64
from typing import Annotated
app = FastAPI()
@app.get("/secure-data")
async def get_secure_data(
authorization: Annotated[str | None, Header()] = None
):
"""Endpoint, защищённый Basic Auth"""
if not authorization or not authorization.startswith("Basic "):
raise HTTPException(status_code=401, detail="Missing authorization")
# Извлекаем закодированную часть
encoded = authorization.split(" ")[1]
try:
# Декодируем Base64
decoded = base64.b64decode(encoded).decode()
username, password = decoded.split(":")
except (ValueError, IndexError):
raise HTTPException(status_code=400, detail="Invalid authorization format")
# Проверяем credentials
if username != "admin" or password != "secret123":
raise HTTPException(status_code=401, detail="Invalid credentials")
return {"data": "This is secure data", "user": username}
Более безопасный способ: хеширование паролей
from fastapi import Depends, HTTPException
from fastapi.security import HTTPBasic, HTTPBasicCredentials
import hashlib
security = HTTPBasic()
# БД с хешированными паролями (в реальности это БД)
USERS = {
"admin": "8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918" # bcrypt хеш от "admin"
}
def verify_password(password: str, hashed: str) -> bool:
"""Проверяет пароль против хеша"""
return hashlib.sha256(password.encode()).hexdigest() == hashed
@app.get("/admin-only")
async def admin_only(credentials: HTTPBasicCredentials = Depends(security)):
"""Эндпойнт с Basic Auth через FastAPI встроенный механизм"""
if credentials.username not in USERS:
raise HTTPException(status_code=401, detail="Invalid user")
# Проверяем пароль
if not verify_password(credentials.password, USERS[credentials.username]):
raise HTTPException(status_code=401, detail="Invalid password")
return {"message": f"Welcome {credentials.username}!"}
Декодирование Basic Auth
import base64
# Декодирование
encoded = "dXNlckBleGFtcGxlLmNvbTpteVNlY3JldFBhc3N3b3Jk"
decoded = base64.b64decode(encoded).decode()
username, password = decoded.split(":")
print(f"Username: {username}")
print(f"Password: {password}")
Структура HTTP запроса с Basic Auth
GET /api/data HTTP/1.1
Host: api.example.com
Authorization: Basic dXNlckBleGFtcGxlLmNvbTpteVNlY3JldFBhc3N3b3Jk
User-Agent: Python-Requests/2.28.0
Проблемы и ограничения Basic Auth
1. НЕ безопасно без HTTPS
# ❌ ОПАСНО: Basic Auth по HTTP
response = requests.get(
"http://api.example.com/data", # Незащищённый HTTP!
auth=("admin", "password123")
)
# ^ Пароль передаётся в открытом виде (хотя и закодирован в Base64)
# ✅ ТОЛЬКО по HTTPS
response = requests.get(
"https://api.example.com/data", # Защищённый HTTPS
auth=("admin", "password123")
)
Почему: Base64 это кодирование, не шифрование. Его легко декодировать.
2. Нет логаута
# Basic Auth включена — отключить её невозможно
# Браузер запомнит credentials и будет отправлять их автоматически
# Единственный способ "выйти" — закрыть браузер или очистить кеш
3. Нет истечения токена
# Credentials не истекают автоматически
# Если украдены, используются вечно (пока не изменен пароль)
4. Нельзя использовать на фронтенде
// ❌ Плохо: пароль в JavaScript
const credentials = 'admin:password123';
const encoded = btoa(credentials);
fetch('/api/data', {
headers: {
'Authorization': `Basic ${encoded}`
}
});
// ^ Пароль видна в исходном коде и в DevTools Network
Когда использовать Basic Auth
✓ Хорошо для:
- API между сервисами (server-to-server)
- Внутренние инструменты
- Временный доступ
- Быстрое прототипирование
- IoT устройства и встроенные системы
✗ Плохо для:
- Публичные веб-приложения
- Мобильные приложения
- Фронтенд (JavaScript)
- Sensitive данные
Альтернативы Basic Auth
# 1. OAuth 2.0 (для публичных API)
# Пример: авторизация через Google, GitHub
# 2. JWT токены
from fastapi import Depends
from fastapi.security import HTTPBearer, HTTPAuthenticationCredentials
security = HTTPBearer()
@app.get("/data")
async def get_data(credentials: HTTPAuthenticationCredentials = Depends(security)):
token = credentials.credentials # JWT токен
# Проверяем и декодируем token
pass
# 3. API Keys
@app.get("/data")
async def get_data(api_key: str = Header(None)):
if api_key != "sk-1234567890":
raise HTTPException(status_code=401)
return {"data": "secure"}
# 4. Digest Auth (с хешем вместо Base64)
# Более безопаснее Basic, но старомодно
Реальный пример: защита внутреннего API
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials
import secrets
app = FastAPI()
security = HTTPBasic()
# Credentials для внутреннего API
VALID_USERS = {
"service-1": "very-secret-password-123",
"service-2": "another-secret-456"
}
async def verify_credentials(credentials: HTTPBasicCredentials = Depends(security)):
"""Проверяет Basic Auth credentials"""
# Используем secrets.compare_digest для защиты от timing attack
correct_username = False
correct_password = False
if credentials.username in VALID_USERS:
correct_password = secrets.compare_digest(
credentials.password,
VALID_USERS[credentials.username]
)
correct_username = True
if not (correct_username and correct_password):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid credentials",
headers={"WWW-Authenticate": "Basic"}
)
return credentials.username
@app.get("/internal/metrics")
async def get_metrics(username: str = Depends(verify_credentials)):
return {"metrics": "data", "accessed_by": username}
Итог
Basic Authorization — это:
- Самый простой метод аутентификации
- ТОЛЬКО для HTTPS
- Хорошо для server-to-server коммуникации
- Плохо для фронтенда и публичных API
- Должна использоваться с хешированием паролей на сервере
- Основана на Base64 кодировании (не шифровании!)
Для производства рекомендуется использовать OAuth 2.0 или JWT вместо Basic Auth.