使用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 %>
它的要点是使用字符串插值来为每个用户创建一个新频道,即
user12
和user123
频道。
问题是这并不安全。任何用户都可以通过粘贴一些 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
不过,这似乎没有任何效果。