Есть ли что-то, чего нам не хватает в том, как встроить серверы Bokeh в Flask, чтобы позволить только Flask общаться с сервером Bokeh?
Клиент (браузер)должен иметь возможность общаться с сервером Bokeh, полная остановка .Все функции сервера Bokeh выполняются через прямое веб-сокет-соединение между сервером Bokeh и браузером.Таким образом, краткий ответ на ваш вопрос «вы не можете».
Тем не менее, вы можете настроить сервер Bokeh на:
- , чтобы автоматически не создавать новые сеансы при каждом соединении
- только для сеансов, имеющих криптографическую подписьID сеанса
- принимать соединения только из источников, занесенных в белый список
Для этого вам необходимо сначала создать секрет для подписания идентификаторов сеанса с помощью команды bokeh secret
, например,
export BOKEH_SECRET_KEY=`bokeh secret`
Затем также установите BOKEH_SIGN_SESSIONS
и установите допустимое происхождение веб-сокета:
BOKEH_SIGN_SESSIONS=yes bokeh serve --allow-websocket-origin=<app origin> app.py
Затем в своем приложении фляги вы явно предоставляете (подписанные) идентификаторы сеанса:
from bokeh.util.session_id import generate_session_id
script = server_session(url='http://localhost:5006/bkapp',
session_id=generate_session_id())
return render_template("embed.html", script=script, template="Flask")
Обратите внимание, что переменная окружения BOKEH_SECRET_KEY
должна быть установлена (и идентична) как для сервера Bokeh, так и для процессов Flask.
Теперь, если кто-либо подключится к серверу Bokeh напрямую, он получит ошибку 403, если URL-адрес соединения не содержит подписанный идентификатор сеанса, подписанный с тем же секретом, с которого был запущен сервер Bokeh.Предположительно, только ваше приложение Flask знает этот секрет, поэтому только оно может успешно инициировать новые сеансы.
Этого достаточно, чтобы полностью обезопасить вещи?Технически любой, кто может получить доступ к строке подключения, отправленной в браузер (например, пользователь, просматривающий приложение, или искушенный злоумышленник MitM, особенно если вы не отключаете HTTPS перед приложением), может извлечь подписанный идентификатор сеанса.Но пока вы устанавливаете разрешенное происхождение веб-сокета, эта информация не может быть использована для инициирования нового соединения из-за пределов вашего приложения.Если кто-то попытается, сервер вернет сообщение 403:
ОШИБКА: bokeh.server.views.ws: Отказ в соединении веб-сокетов от Origin 'http://localhost:5006'; use --allow-websocket-origin = localhost: 5006 или установить BOKEH_ALLOW_WS_ORIGIN = localhost: 5006, чтобы разрешить это;в настоящее время мы разрешаем origins {'localhost: 8000'}
Я не думаю, что вы можете подделать заголовок Origin из реального браузера, хотя, возможно, кто-то может создать модифицированный Chrome из исходного кода (это не легко, но не невозможно) подделать.Если вам нужно остерегаться этого, то Bokeh Project Discourse , вероятно, является лучшим местом для продолжения обсуждения, так как оно несколько открытое и может указывать на разработку новых функций (например, возможность указать соединениеограничение для сессий, или чтобы идентификаторы сессий никогда не использовались повторно.
Для справки, здесь приведен полный пример, который также встраивает сервер Bokeh непосредственно в процесс Flask (если вам нужно уменьшить или ожидатьнесколько одновременных пользователей, это было бы слишком наивным развертыванием):
https://gist.github.com/bryevdv/481fc64c59620acb74c64bff0f4d47d0
В качестве последнего комментария вы, возможно, также (дополнительно) можете поместить URL-адрес сервера Bokeh позади прокси-сервера аутентификации некоторыхсортировать, чтобы предотвратить обновление WS в первую очередь без аутентификации.Хотя я не уверен, что именно это будет выглядеть не по назначению.Это также лучше обсудить на Дискурсе