Bottle-Cork — це легка бібліотека автентифікації та авторизації для вебзастосунків на Python, побудованих на мікрофреймворку Bottle. Вона дає невеликому self-hosted застосунку те, що інакше довелося б абияк реалізовувати самому: облікові записи, рольові права, підписані cookie-сесії, реєстрацію та скидання пароля. У цьому посібнику розбираємо, як працює Cork, чим він відрізняється від інших варіантів на Python і як безпечно запустити застосунок з автентифікацією на власному сервері.
Що робить Bottle-Cork — коротко
| Можливість | Як реалізує Cork |
|---|---|
| Облікові записи | Логін, хеш пароля, e-mail, роль і довільні дані профілю |
| Авторизація | Іменовані ролі з цілочисловим рівнем; декоратори вимагають мінімальний рівень |
| Сесії | Підписані cookie з терміном дії через Beaker; серверне сховище сесій не потрібне |
| Реєстрація | Потік з очікуванням підтвердження та токеном у листі |
| Скидання пароля | Підписаний токен з обмеженим часом життя, надісланий поштою |
| Сховище | 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(), а цілісність сесії цілком залежить від секретного ключа підпису — довгого, випадкового й такого, що не зберігається в дереві вихідного коду.
Ролі та авторизація
Тримайте кількість ролей невеликою, а розриви рівнів широкими (наприклад 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 не заважає.
Харденінг сервера за вашим входом
Автентифікація не сильніша за машину, на якій працює. Ідеальна сторінка входу марна, якщо порт бази даних відкритий в інтернет або стара адмінка відповідає на 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 у сотню рядків можна спокійно виставити у відкритий інтернет.