Машинный перевод под контролем человека
Этот контент переведён с помощью машинной генерации, направляемой составленными людьми глоссариями и руководствами по стилю. Поскольку текст не проверяется вручную построчно, возможны отдельные ошибки или неестественные формулировки.
В случае любых расхождений авторитетным источником считается оригинальная версия на английском языке.
title: Безопасность description: Встроенные механизмы безопасности starlette-admin: защита от CSRF, безопасность загрузки файлов и контроль доступа.
Безопасность
starlette-admin включает встроенные меры защиты от рисков, связанных с эксплуатацией панели администрирования. Защита от межсайтовой подделки запросов (CSRF) и ограничения на размер экспортируемых и импортируемых данных активируются сразу после создания экземпляра класса Admin.
Эти настройки по умолчанию защищают интерфейс от распространённых атак, но не заменяют стандартную защиту инфраструктуры развёртывания. Ответственность за безопасность транспортного уровня (HTTPS/TLS), сетевой контроль доступа, аутентификацию пользователей (см. Аутентификацию), обновление зависимостей и аудит безопасности остаётся на вас. На этой странице описаны автоматические защиты, параметры, которые вы настраиваете сами, а также параметр secret_key, который обязательно нужно задать в рабочем окружении.
Что включено по умолчанию
from sqlalchemy import create_engine
from starlette.applications import Starlette
from starlette_admin.contrib.sqla import Admin
engine = create_engine("sqlite:///admin.sqlite")
app = Starlette()
admin = Admin(engine, title="My Admin")
admin.mount_to(app)
Даже без каких-либо параметров безопасности экземпляр панели защищает от нескольких распространённых уязвимостей:
- Защита от CSRF: активна для каждой формы и каждого jQuery AJAX-запроса, включая действия со строками и диалоги подтверждения.
- Flash-сообщения: передаются в подписанной cookie, поэтому
SessionMiddlewareне требуется. - Санитизация имён файлов: применяется к каждому файлу, загружаемому через storage backend.
- Проверка содержимого изображений: загрузки в
ImageFieldпроверяются на уровне байтов с помощью Pillow, если он установлен. - Ограничения экспорта: не более 100 000 строк за один запрос — это предотвращает исчерпание ресурсов и отказ в обслуживании.
- Ограничения импорта: не более 10 МБ за один запрос — это ограничивает риск переполнения памяти.
Ещё одна защита доступна, но отключена по умолчанию: экранирование, которое предотвращает инъекцию формул в CSV- и табличные экспорты (XLSX, XLS, ODS). Подробнее см. Инъекция формул.
В разделах ниже описаны эти защиты и способы настройки пороговых значений, которые находятся под вашим контролем.
Секретный ключ
secret_key — это криптографическая основа для подписания двух cookie: CSRF-токена и cookie flash-сообщений. Обе используют библиотеку itsdangerous, поэтому клиент может прочитать содержимое cookie, но не может подделать или изменить его без ключа.
Всегда задавайте явный секретный ключ в рабочем окружении
Если параметр secret_key не указан, экземпляр Admin генерирует случайный ключ при запуске и выдаёт предупреждение UserWarning. Для локальной демонстрации этого достаточно, однако в развёртывании с несколькими воркерами такой вариант не работает. При запуске нескольких воркеров, например через uvicorn --workers 4, Gunicorn или несколько контейнеров, каждый процесс генерирует собственный ключ. CSRF-токен, подписанный тем воркером, который отдал форму, не пройдёт проверку, если отправку обработает другой воркер — в результате часть запросов будет получать ошибки недействительного CSRF-токена, казалось бы, случайным образом. Задайте secret_key явно до того, как масштабируетесь более чем на один процесс.
Защита от CSRF
CSRFMiddleware использует схему подписанного double-submit cookie для предотвращения межсайтовой подделки запросов. Он устанавливает cookie starlette_admin_csrftoken для безопасных HTTP-методов (GET, HEAD, OPTIONS и TRACE). Для изменяющих запросов он сверяет эту cookie либо с заголовком X-CSRFToken, либо со скрытым полем формы csrftoken.
Каждый встроенный шаблон панели (create, edit и login) выводит скрытое поле автоматически:
Поставляемый JavaScript также добавляет заголовок к каждому jQuery AJAX-запросу, поэтому действия со строками и другие асинхронные взаимодействия защищены без дополнительного кода. Вызывайте csrf_input(request) самостоятельно только при создании форм вне стандартных шаблонов. См. Custom Views.
Загрузка файлов
Каждая загрузка, проходящая через storage backend, проходит санитизацию функцией secure_filename. Компоненты пути, используемые для обхода каталогов, удаляются, а символы вне диапазона [A-Za-z0-9_.-] заменяются подчёркиваниями (_). Отключить это поведение невозможно.
Ограничения по типу содержимого и размеру задаются для каждого поля с помощью параметров accept и max_size:
from starlette_admin.fields import FileField
class DocumentView:
invoice = FileField(accept=".pdf,.docx", max_size=5 * 1024 * 1024) # лимит 5 МБ
Без них FileField принимает файлы любого типа и размера. Исключение составляет ImageField: по умолчанию он использует значение accept="image/*", а при установленном Pillow добавляет валидатор, который открывает загрузку через PIL.Image, чтобы убедиться, что байты действительно декодируются как изображение, вместо доверия метаданным, переданным браузером.
Ограничивайте размер запроса на уровне веб-сервера
Не полагайтесь только на max_size. Проверка на уровне приложения выполняется лишь после того, как сервер получил весь payload запроса. Чтобы предотвратить атаки типа «отказ в обслуживании» (DoS), ограничьте размер тела запроса в конфигурации веб-сервера, например с помощью client_max_body_size в NGINX или аналогичного параметра вашего балансировщика нагрузки.
Расширения файлов и заголовки Content-Type можно подделать
Атрибут accept опирается на расширение имени файла и переданный браузером заголовок Content-Type, причём и то и другое злоумышленник может подделать. Файл с именем invoice.pdf может содержать исполняемый код.
Для файлов, не являющихся изображениями, дополняйте accept пользовательским валидатором, который проверяет magic bytes файла. Библиотеки вроде filetype и python-magic позволяют проверить фактический формат файла:
import filetype
from starlette.datastructures import UploadFile
from starlette.requests import Request
from starlette_admin.fields import BaseField
ALLOWED_DOCUMENT_MIME_TYPES = {
"application/pdf",
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
}
def validate_document_type(
request: Request, field: BaseField, upload: UploadFile, form_values: dict
) -> None:
upload.file.seek(0)
try:
header = upload.file.read(2048)
kind = filetype.guess(header)
detected = kind.mime if kind else "application/octet-stream"
finally:
upload.file.seek(0)
if detected not in ALLOWED_DOCUMENT_MIME_TYPES:
raise ValueError(
f"Invalid file type '{detected}'. Only PDF, DOC, and DOCX are allowed."
)
Подключите валидатор через FileField(..., validators=[validate_document_type]). Полный пример реализации см. в examples/04-filestorage.
Ограничения экспорта
from starlette_admin.export import ExportConfig
admin = Admin(engine, title="My Admin", export_config=ExportConfig(max_rows=50_000))
| Атрибут | По умолчанию | Описание |
|---|---|---|
max_rows |
100_000 |
Максимальное количество строк на один запрос экспорта. При превышении лимита выводится сообщение об ошибке, и пользователь возвращается к списку. Установите None, чтобы снять ограничение. |
restrict_url_download |
True |
Применяется к ссылкам только на файлы по URL. Ограничивает экспортный ZIP файлами, источник которых совпадает с base_url панели. |
max_download_size |
20 MB |
Максимальный размер файла, загружаемого по URL и упаковываемого в экспортный ZIP. Более крупные файлы пропускаются с записью предупреждения в лог. |
safe_download_url |
None |
Пользовательский callback с сигнатурой (url, request) -> str. |
О том, как формируется ZIP-архив, см. в разделе Export & Import.
Инъекция формул
Табличные редакторы интерпретируют значение ячейки, начинающееся с символа =, +, - или @, как формулу. Если недоверенный пользователь сохранит в экспортируемое поле payload вида =HYPERLINK(...), табличное приложение выполнит его при открытии файла администратором. Эта атака известна как CSV injection, или инъекция формул.
Поскольку экспортируемые значения записываются в точности так, как они хранятся в базе данных, экранирование формул по умолчанию отключено. CSV-экспортёр и экспортёры Tablib (xlsx, xls и ods) принимают параметр escape_formulas. Когда он включён, к любой строке, начинающейся с триггерного символа, добавляется одинарная кавычка в начале ('), что заставляет приложение отображать значение как обычный текст.
Включайте экранирование формул для данных, вводимых пользователями
Если любая учётная запись без прав администратора может записывать данные в экспортируемое поле, установите escape_formulas=True. Иначе значения, контролируемые злоумышленником, смогут выполнять системные команды или похищать данные при открытии файла пользователем локально.
Чтобы включить экранирование, замените строковый формат на явный экземпляр экспортёра:
from starlette_admin.contrib.sqla import ModelView
from starlette_admin.export import CsvExporter, TablibExporter
class ProductView(ModelView):
exporters = [
CsvExporter(escape_formulas=True),
TablibExporter("xlsx", escape_formulas=True),
"json",
]
Ограничения импорта
from starlette_admin.importers import ImportConfig
admin = Admin(
engine,
title="My Admin",
import_config=ImportConfig(
max_upload_size=5 * 1024 * 1024,
max_rows=50_000,
),
)
| Атрибут | По умолчанию | Описание |
|---|---|---|
max_upload_size |
10 MB |
Проверяется сразу после поступления запроса, до любого разбора данных. |
max_rows |
100_000 |
Максимальное количество строк на один запрос импорта. Панель подсчитывает строки в предварительном проходе и отклоняет файл большего размера ответом HTTP 400 до создания какой-либо записи в базе данных. Установите None, чтобы снять ограничение. |
Импорт полностью отклоняет ZIP-архивы, что исключает риск атак «ZIP-бомбой» на этот endpoint. Поля FileField и ImageField также исключены из массового импорта, так как для них по умолчанию задано exclude_from_import=True: файлы прикрепляются по одному через формы create или edit.
Чего эта страница не охватывает
Встроенные защиты закрывают риски внутри кодовой базы панели. Они не обеспечивают безопасность вашей архитектуры в целом. Следующие организационные меры выходят за рамки starlette-admin и остаются на вашей стороне:
- Безопасность транспорта: обслуживайте панель по HTTPS. Cookie CSRF и flash-сообщений подписываются, но не шифруются, поэтому любой, кто перехватит трафик plain HTTP, сможет их прочитать.
- Аутентификация и авторизация: экземпляр
Adminобщедоступен, пока вы не подключитеAuthProvider. Без него открыты все endpoint'ы и маршруты. См. Аутентификацию. - Сетевая доступность: если панели не требуется публичный доступ, разместите её за firewall, VPN или IP allowlist.
- Актуальность зависимостей: следите за бюллетенями безопасности и своевременно обновляйте
starlette-admin, Starlette, драйвер вашей ORM и остальные зависимости. - Действия после аутентификации: защита от CSRF и проверка загрузок не ограничивают возможности вошедшего пользователя. Гранулярный контроль доступа целиком определяется проверками прав, которые вы пишете в
is_accessible,can_create,can_editиcan_delete. См. Аутентификацию.
Рассматривайте эту страницу как руководство по настройке пакета, а не как чек-лист по защите всего рабочего окружения.
Что дальше
- Export & Import: диалог экспорта, жизненный цикл предпросмотра импорта и структура ZIP-архива.
- File Storage: шаблоны настройки storage backend'ов для
FileFieldиImageField. - Authentication: как
secret_keyуправляет сессиями входа и проверками CSRF после подключения auth-провайдера.