2

使用websocket-rails,我可以在我的控制器中使用以下代码来欺骗 websocket 发布事件:

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

我的目标是仅为当前用户创建一个发布订阅频道。以事件“发送新的聊天消息”为例。我只想推送这个事件接收者的频道。

我目前正在根据他们的 ID 为每个用户创建一个唯一的频道名称。我将以下代码放在我的控制器中(在别处定义了 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 %>

它的要点是使用字符串插值来为每个用户创建一个新频道,即 user12user123频道。

问题是这并不安全。任何用户都可以通过粘贴一些 Javascript 来访问任何其他人的私人频道。例如,如果用户 #1 想要访问用户 #2 的新闻提要,他们只需键入dispatcher.subscribe('user2').

你会如何解决这个问题?是否有另一个内置了此功能的 pub-sub 库?

查看有关该主题的 WebsocketRails wiki 条目,我尝试将以下代码添加到 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

不过,这似乎没有任何效果。

4

0 回答 0