Канал websocket для "текущего пользователя"

Используя websocket-rails, я могу использовать следующий код в моем контроллере, чтобы обмануть событие публикации websocket:

WebsocketRails[:channel_name].trigger('event_name', { foo: "bar" }.to_json)

Моя цель - создать канал pub-sub только для текущего пользователя. Возьмем, к примеру, событие "Новое сообщение в чате отправлено". Я хочу выдвинуть это событие только на канал получателя.

В настоящее время я создаю уникальное имя канала для каждого пользователя на основе его идентификатора. Я поместил следующий код в мой контроллер (определив метод current_user в другом месте:

WebsocketRails[:"user#{current_user.id}"].trigger("event_name", { foo: "bar" }.to_json)

И затем в моем Javascript я подписываю текущего пользователя на его собственный канал со следующим:

<% if @current_user %>
  var dispatcher = new WebSocketRails('localhost:3000/websocket');
  channel = dispatcher.subscribe('user<%= @current_user.id %>'); 
  channel.bind('event_name', function(data) {
    console.log(data)
  });
<% end %>

Суть его заключается в использовании интерполяции строк для создания нового канала для каждого пользователя, т.е.user12 а также user123 каналы.

Проблема в том, что это не совсем безопасно. Любой пользователь может получить доступ к чьему-либо частному каналу, просто вставив в него некоторый Javascript. Например, если пользователь № 1 хочет получить доступ к новостной ленте пользователя № 2, он может просто набрать dispatcher.subscribe('user2'),

Как бы вы решили эту проблему? Есть ли другая библиотека pub-sub, в которую встроена эта функция?

Просматривая вики-статью WebsocketRails по этой теме, я попытался добавить следующий код в config / initializers / websockets.rb

WebsocketRails::EventMap.describe do
  namespace :websocket_rails do
    subscribe :subscribe_private, to: ConnectionsController, with_method: :authorize_channels
  end
end

И следующее к app / controllers / connections_controller.rb

class ConnectionsController < WebsocketRails::BaseController
  def authorize_channels
    channel_name = WebsocketRails[message[:channel]]
    current_user = User.find_by(id: session["current_user_id"])
    if current_user && "user#{current_user.id}".eql?(channel_name)
      accept_channel current_user
    else
      deny_channel({ message: "auth failed" })
    end
  end
end

А потом в другом месте, я звоню WebsocketRails[:"user#{@current_user.id}"].make_private

Это, похоже, не имеет никакого эффекта.

0 ответов

Другие вопросы по тегам