node.js — чат в реальном времени на PHP + Redis + Pub / Sub + WebSockets (+ NodeJS)

Я хочу разработать чат в реальном времени с каналами, и это мои потребности:

  • PHP-бэкэнд для управления сайтом
  • Redis как сеанс и основное хранилище данных
  • Pub / Sub для отправки сообщений только заинтересованным пользователям канала
  • одно соединение WebSocket, с помощью которого сообщения будут отправляться и приниматься.
  • (необязательно) NodeJS для использования больших пакетов npm, таких как timesync или socket.io

Я вижу две разные архитектуры для достижения этой цели:

  • с Socket.io

    socket.io

  • с Crossbar.io

    crossbar.io

Это мои вопросы:

  1. Какую архитектуру мне выбрать и почему?
  2. Ключом является то, что идентификатор пользователя не может быть получен от клиента, потому что он может быть искажен. Итак, в первой архитектуре я думаю, что к каждому сообщению сокета я должен прикрепить значение PHPSESSID из cookie, а на стороне сервера — получить сеанс PHP из Redis. Я прав или есть лучший способ получить идентификатор пользователя?
  3. Интересно, можно ли получить идентификатор пользователя во второй архитектуре иначе?

Редактировать:

я выбрал Crossbar.io, потому что это очень мощный и позволяет общаться много разных языковых приложений в режиме реального времени. Изучив примеры, я придумываю следующее:

  • При каждом входе в систему пользователь генерировал секретный ключ в базе данных.

  • PHP-клиент (Thruway) подключается к серверу Crossbar и регистрирует собственный аутентификатор WAMP-CRA

  • Браузер пользователя подключается к серверу Crossbar и подвергается сомнению. Секрет и auth_id (идентификатор пользователя) загружаются из БД при загрузке страницы, поэтому
    может выполнить вызов и отправить ответ.

  • PHP-аутентификатор ищет в БД пользователя с предоставленным секретом и идентификатором, равным auth_id. Если есть, то он успешно аутентифицируется
    сессия. Теперь мы можем верить, что auth_id — это настоящий идентификатор пользователя.

Это мой вопрос:

  1. Как я могу получить auth_id при подписке?

  2. Я также добавил аутентификацию cookie, и браузер запоминается после аутентификации. Но когда я смотрю в Chrome DevTools в локальном хранилище нет ни cookie, ни значения. Даже после очистки кэша мой браузер все еще запоминается перекладина. Интересно, как это возможно?

Edit2:

Возможно, меня неправильно поняли, но главным вопросом был выбор подходящей архитектуры и получение идентификатора доверенного пользователя. Там не было никакого внимания, поэтому я наградил награду, и после этого я был понижен. Я много читал о приложениях в реальном времени и, наконец, решил использовать Crossbar.io, поэтому я отредактировал вопрос, чтобы иметь к нему отношение. Тогда люди начали голосовать, предлагая другую архитектуру, но не отвечая на мои вопросы. Ведь мне удалось сделать это самому и представить свой ответ.

3

Решение

Я глубоко осветил Streamer, который используется НАСА для пересылки грузовых данных в секунду. Самый надежный сервер для обмена сообщениями в режиме реального времени.
Мощные веб-приложения, приложения для мобильных устройств, планшетов, компьютеров и IoT.

Оптимизированный поток данных для Интернета и мобильных устройств.
Lightstreamer поддерживает несколько форм обмена сообщениями в реальном времени. Он достаточно гибок, чтобы использоваться в любом сценарии, включая критически важные приложения.
► Передача данных в реальном времени и веб-сокеты
► Сообщения в приложении и push-уведомления
► Паб-саб с разветвленной трансляцией и индивидуальным обменом сообщениями
► Брандмауэр и прокси дружественный
► Адаптивное регулирование пропускной способности

Что касается вашего первого вопроса, чтобы получить auth_id для подписки, просто следите за подписками на соединения, а затем сохраняйте уровень при успешном соединении.
Кроме того, файлы cookie не рекомендуются, используйте jwt.JSON Web Tokens — это открытый, стандартный отраслевой метод RFC 7519 для безопасного представления заявок между двумя сторонами. Аутентификация является одной из основных частей каждого приложения. Безопасность — это то, что постоянно меняется и развивается. JWT помогает вам решить эту проблему. Поскольку она не имеет состояния.

1

Другие решения

PHP Ratchet — одна из лучших реализаций, которую я использовал для связи в реальном времени через WebSockets. Он основан на ZMQ Sockets, который используется в нескольких онлайн-играх и приложениях для чата.

Следующие примеры помогут вам начать работу довольно быстро и ответят на ваши вопросы о auth_id и подписках:

http://socketo.me/docs/hello-world

http://socketo.me/docs/push

Обзор архитектуры:

http://socketo.me/docs/push#networkarchitecture

Я бы посоветовал создавать отдельные соединения (toppics) для каждого разговора, так как это не влияет на производительность и добавляет дополнительный уровень безопасности для каждого чата.

0

Каждый пример чата в реальном времени, который я видел, получал идентификатор от клиента. Это небезопасно, потому что клиент легко может манипулировать им, поэтому мне нужно было найти другой метод. После прочтения Спецификации WAMP Я наконец-то понял, что мне нужно аутентифицировать пользователя не только в приложении, но и в Crossbar.io. Я выбрал динамический метод WAMP-CRA и реализовал его следующим образом:

  • Приложение PHP подключается к серверу Crossbar и регистрирует собственный аутентификатор (аналогично пример)
  • После входа пользователя в приложение генерируется Секретный ключ для него и сохраняется в базе данных. После выхода из системы ключ уничтожается.
  • Процедура:

    1. Каждая загруженная страница содержит Идентификатор пользователя а также Секретный ключ загружается из БД:

      <script>
      auth_id = '<?php echo $user->id ?>';
      secret_key = '<?php echo $user->secret_key ?>';
      </script>
      
    2. Пользовательский браузер подключается к Crossbar.io сервер и получить ответ с запросом от пользовательского аутентификатора.
    3. Это вычислить подпись, используя ключ и отправить вместе с auth_id в Crossbar.io сервер
    4. Аутентификатор достает из БД секрет за предоставленный auth_id и рассчитать подпись. Затем сигнатуры сравниваются, и если они равны, аутентификация проходит успешно.
    5. Сейчас auth_id содержит идентификатор пользователя, и мы можем доверять его значению. Теперь вы можете ссылаться на раздел ‘Как я могу получить auth_id при подписке?’.

Как я могу получить auth_id при подписке?

По умолчанию издатели и подписчики не знают друг о друге, но документация показать, что есть возможность изменить его, настроив раскрытие личности вызывающего абонента. Тогда вы можете получить auth_id из деталей обратного вызова:

  • PHP:

    $onEvent = function ($args, $argsKw, $details, $publicationId) use ($session) {
    $auth_id = $details->publisher_authid;
    ...
    }
    $session->register('com.example.event', $onEvent);
    
  • JS:

    function on_event(args, kwargs, details) {
    auth_id = details['publisher_authid'];
    ...
    }
    session.subscribe('com.example.event', on_event);
    

Я также добавил аутентификацию cookie, и браузер запоминается после аутентификации. Но когда я смотрю в Chrome DevTools, в локальном хранилище нет ни куки, ни значения. Даже после очистки кеша мой браузер до сих пор запоминается по Crossbar. Интересно, как это возможно?

Прежде всего, очистка кеша и полная перезагрузка не удаляют куки. Когда я задавал этот вопрос, был какой-либо файл cookie, но сегодня я вижу cbtid:
печенье
Два дня назад было обновление Chrome, так что, возможно, это было вызвано ошибкой в ​​предыдущей версии.

0