Bottle-Cork — это лёгкая библиотека аутентификации и авторизации для веб-приложений на Python, построенных на микрофреймворке Bottle. Она даёт небольшому self-hosted приложению то, что иначе пришлось бы кое-как реализовывать самому: учётные записи, ролевые права, подписанные cookie-сессии, регистрацию и сброс пароля. В этом руководстве разбираем, как работает Cork, чем он отличается от других вариантов на Python и как безопасно запустить приложение с аутентификацией на своём сервере.
Что делает Bottle-Cork — кратко
| Возможность | Как реализует Cork |
|---|---|
| Учётные записи | Логин, хеш пароля, e-mail, роль и произвольные данные профиля |
| Авторизация | Именованные роли с целочисленным уровнем; декораторы требуют минимальный уровень |
| Сессии | Подписанные cookie с истечением через Beaker; серверное хранилище сессий не требуется |
| Регистрация | Поток с ожиданием подтверждения и токеном в письме |
| Сброс пароля | Подписанный токен с ограниченным временем жизни, доставляемый по e-mail |
| Хранилище | JSON-файлы, MongoDB или SQLAlchemy |
Как работает Cork
Cork располагается между маршрутизацией Bottle и вашими обработчиками. Каждый защищённый запрос вызывает метод Cork, который проверяет cookie-сессию, определяет текущего пользователя и либо пропускает обработчик, либо прерывает выполнение редиректом на страницу входа. Пользователи, роли и ожидающие регистрации хранятся в бэкенде, выбранном при запуске. Для одного небольшого приложения достаточно JSON; при конкурентной записи переходите на MongoDB или SQLAlchemy.
Роли упорядочены по целочисленному уровню. admin на уровне 100 может всё, что может editor на уровне 50, и больше. Обработчики объявляют минимальный требуемый уровень, поэтому авторизация выражается один раз — на маршруте, а не размазана по бизнес-логике.
Минимальное приложение с аутентификацией
from bottle import Bottle, request, redirect
from cork import Cork
from beaker.middleware import SessionMiddleware
aaa = Cork('conf_dir') # бэкенд: users.json, roles.json, ...
app = Bottle()
@app.post('/login')
def login():
aaa.login(request.forms.get('user'),
request.forms.get('pwd'),
success_redirect='/dashboard',
fail_redirect='/login')
@app.route('/dashboard')
def dashboard():
aaa.require(fail_redirect='/login')
return 'Hello %s' % aaa.current_user.username
@app.route('/admin')
def admin():
aaa.require(role='admin', fail_redirect='/login')
return 'Admin area'
wrapped = SessionMiddleware(app, {'session.type': 'cookie',
'session.encrypt_key': 'CHANGE-ME',
'session.validate_key': True})
Две мысли, которые стоит унести, даже если вы никогда не используете Cork: авторизация должна стоять на маршруте одним вызовом require(), а целостность сессии целиком зависит от секретного ключа подписи — длинного, случайного и не хранящегося в дереве исходников.
Ищете сервер, который просто работает?
Valebyte VPS — NVMe, поддержка 24/7, развёртывание за 60 секунд.
Роли и авторизация
Держите число ролей небольшим, а разрывы уровней широкими (например 0 = аноним, 30 = пользователь, 60 = редактор, 100 = админ). Широкие разрывы позволяют позже вставить новый уровень без перенумерации. Никогда не давайте права по имени пользователя — проверяйте уровень роли. Имена меняются, ими прикрываются в тикетах поддержки, и они утекают в логи.
Безопасность паролей и сессий
Cork хранит хеши паролей, а не пароли, и подписывает cookie-сессии. Это базовый уровень, а не финиш. Задайте реальную минимальную длину пароля, ограничьте частоту запросов к маршруту входа против credential stuffing, задайте разумный таймаут сессий и меняйте ключ подписи при его утечке. Отдавайте всё по HTTPS, чтобы cookie нельзя было прочитать в канале, и ставьте флаги Secure и HttpOnly.
Bottle-Cork против других вариантов на Python
| Вариант | Фреймворк | Для чего лучше | Компромисс |
|---|---|---|---|
| Bottle-Cork | Bottle / WSGI | Небольшие self-hosted приложения с ролями без БД | Минимум экосистемы; почту и rate-limit подключаете сами |
| Flask-Login | Flask | Управление сессиями в приложениях Flask | Только сессии; роли и регистрация — на вас |
| Authlib | Любой | Провайдеры и клиенты OAuth2 / OpenID Connect | Тяжелее; избыточно для одного внутреннего приложения |
| Django auth | Django | Полноценные приложения на ORM Django | Придётся принять весь фреймворк |
| Authelia / Keycloak | Отдельный SSO | Защита нескольких сервисов одним входом | Отдельный сервис, который сам нужно защищать |
Если у вас уже больше пары self-hosted сервисов, отдельный провайдер идентичности вроде Keycloak часто лучше в долгую — см. наше руководство по установке Keycloak для SSO и IAM. Для одного приложения на Bottle Cork не мешается под ногами.
Ищете сервер, который просто работает?
Valebyte VPS — NVMe, поддержка 24/7, развёртывание за 60 секунд.
Харденинг сервера за вашим входом
Аутентификация не сильнее машины, на которой работает. Идеальная страница входа бесполезна, если порт базы данных открыт в интернет или старая админка отвечает на 8080. Считайте сам хост частью границы аутентификации:
- Файрвол по принципу default-deny. Открывайте только 443 (и SSH — по ключу, желательно на нестандартной конфигурации). Инструменты в традиции Firelet, а сегодня
nftablesилиufw, позволяют явно описать разрешённый трафик и проверять его как набор правил, а не как груду разовых команд. - Fail2ban на логах входа и SSH, чтобы банить источники перебора.
- TLS везде с автопродлением сертификатов; весь HTTP — редиректом на HTTPS.
- Обратный прокси (nginx или Caddy) перед процессом Python, чтобы приложение не смотрело в интернет напрямую, а заголовки и лимиты задавались в одном месте.
- Минимум привилегий: запускайте приложение под непривилегированным пользователем, а файл бэкенда делайте читаемым только этим пользователем.
Первые полчаса на новой машине задают тон всему остальному — наш чек-лист по защите выделенного сервера сразу после выдачи разбирает файрвол, SSH и обновления по порядку.
Какой сервер выбрать для self-hosted приложения
Как только входят реальные пользователи, вам нужны предсказуемые CPU и память, фиксированный IP и полный контроль над файрволом — ничего из этого в полной мере не даёт shared-хостинг. Приватный виртуальный сервер годится для лёгкого приложения; выделенный сервер — верный выбор, когда вы храните реальные данные пользователей, держите базу или нужны гарантированные ресурсы без шумных соседей. Если ограничивает бюджет, недорогой выделенный сервер всё равно даёт изоляцию и контроль файрвола, от которых зависит аутентификация.
Сам Bottle-Cork небольшой — и в этом суть: важна не библиотека, а дисциплина вокруг неё — хешированные учётные данные, ролевая авторизация, подписанные сессии и защищённый хост под ними. Сделайте это правильно — и даже приложение на Bottle в сотню строк можно спокойно выставить в открытый интернет.