denisbondar
@denisbondar
Python, PHP developer

Как аутентифицировать пользователя приложения при подключении к RabbitMQ по протоколу WEB-STOMP?

Исходные данные
Дано: WEB-приложение на PHP с фронтендом на JS, а также RabbitMQ, который в том числе используется как websocket сервер, работающий по протоколу STOMP (web-stomp-plugin).

Схема взаимодействия стандартная: фронтенд приложение, используя stomp.js, подключается к RabbitMQ, авторизуясь при помощи логина и пароля. На RabbitMQ созданы exchange типа fanout для каждого зарегистрированного пользователя веб-приложения - они используются для передачи push-сообщений в сторону фронтенда. Фронтенд после загрузки сразу же подключается к RabbitMQ, создает временную автоубиваемую очередь и подключает ее к конкретному exhange, ассоциированному с текущим пользователем web-приложения. Теперь, если бекенд отправит сообщение в exchange пользователя - оно сразу же попадет во все очереди, подключенные к нему и будет передано в сторону фронтенд по протоколу stomp. Эта схема работает отлично.

Проблема
Дело в том, что изучив исходный js-код на фронтенде или же трафик, можно найти там логин и пароль подключения к RabbitMQ, а также наименование exchange, к которой подключается очередь, созданная фронтендом. Имея эти данные можно не санкционировано подключаться к RabbitMQ, а также создавать очередь и подключать ее к любому exchange, перехватывая информацию, которая предназначается другим пользователям.

Вопрос
Каким образом можно организовать доступ к конкретному exchange только в пределах известной сессии? Или же каким-то другим способом? Наверняка есть стандартные решения этого вопроса безопасности, реализуемые средствами в RabbitMQ.
  • Вопрос задан
  • 722 просмотра
Решения вопроса 2
@BorisKorobkov Куратор тега PHP
Web developer
Создавать очереди должен только бэкенд (PHP). Он же выдает уникальные ID (например, session_id или md5) клиенту. Далее клиент подключается к ранее созданной очереди с этим ID.

Теоретически клиент может брутфорсить очереди, но можете сами посчитать, сколько там будет возможных комбинаций.

P.S. Логин/пароль на клиенте нет смысла использовать, ибо он все легко равно перехватывается.
Ответ написан
@yarkin
Boris Korobkov дал ценное замечание по поводу того, что всем должен рулить сервер и нужно добавить элемент случайности в имена, дополню его несколькими рекомендациями.

1) Если очередь будет создана сервером, то auto-delete не будет работать, если клиент не подпишется на неё.
2) Не забывайте, что если два клиента (например, две вкладки или две сессии одного пользователя) подключатся к одной очереди, то сообщение получит только один из них. В своих решениях я использовал подход, что очередь создавалась клиентом, а обменник сервером, но необходимо убедиться, что до RabbitMQ доходят только легитимные запросы (от авторизованных клиентов) и пользователь ограничен в правах создавать только нужные очереди и подписывать их на нужные обменники.
3) Рекомендовал бы не выставлять порт web-stomp плагина без доп.защиты (например, HAProxy), которая позволит защитить RabbitMQ от перегрузки подключениями.

P.S. Писал статью на Хабр год назад о подобной системе, может быть что-то будет интересное в ней ещё - https://habr.com/post/341068/
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы