Rails Action Cable:如何授权传入连接?

Posted

技术标签:

【中文标题】Rails Action Cable:如何授权传入连接?【英文标题】:Rails Action Cable: How to authorize incoming connection? 【发布时间】:2018-10-07 18:43:17 【问题描述】:

我正在尝试在 websocket 连接上实现授权(rails 5.2.1)

按照rubyonrails guideline,我创建了如下的connection.rb:

# app/channels/application_cable/connection.rb

module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = find_verified_user
    end

    private
      def find_verified_user
        if verified_user = User.find_by(id: cookies.encrypted[:user_id])
          verified_user
        else
          reject_unauthorized_connection
        end
      end
  end
end

很遗憾,所有的 websocket 连接请求都被拒绝了。 (我发现 cookies.encrypted[:user_id] 返回 nil。)

Started GET "/cable" for ::1 at 2018-10-07 21:33:46 +0300
Started GET "/cable/" [WebSocket] for ::1 at 2018-10-07 21:33:46 +0300
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
  User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."is_active" = $1 AND "users"."id" IS NULL LIMIT $2  [["is_active", true], ["LIMIT", 1]]
  ↳ app/channels/application_cable/connection.rb:12
An unauthorized connection attempt was rejected
Failed to upgrade to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
Finished "/cable/" [WebSocket] for ::1 at 2018-10-07 21:33:46 +0300
Finished "/cable/" [WebSocket] for ::1 at 2018-10-07 21:33:46 +0300

请指导我如何访问 app/channels/application_cable/connection.rb 中的当前用户信息?

【问题讨论】:

【参考方案1】:

为了从 Devise 获取 current_user,您需要更改您的 connection.rb,如下所示:

module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = find_verified_user
      logger.add_tags 'ActionCable', current_user.email
    end

    protected

    def find_verified_user # this checks whether a user is authenticated with devise
      if verified_user = env['warden'].user
        verified_user
      else
        reject_unauthorized_connection
      end
    end
  end
end

【讨论】:

我试过 cookies.signed 而不是加密,但没有任何改变。我还在“find_verified_user”方法上启用了调试器,似乎 cookies.signed[:user_id] 为零(尽管用户在 rails 中经过身份验证):(byebug) cookies.signed[:user_id] nil 顺便说一句,为了使用 Action Cable,我最近将这个应用程序从 Rails 4.2.10 升级到 Rails 5.2.1 。我只是想让你知道,因为这不是一个新的 rails 5.2.1 应用程序,我可能会遗漏一些可能需要的其他配置? 您是否使用devise 作为身份验证解决方案或任何其他用于此目的的gem? 我正在使用设计 那么我认为您需要更新您的connection.rb 文件,以便它与设计映射。例如。 if verified_user = env['warden'].user 在验证用户的情况下。查看以下链接,了解如何在使用 Devise 时设置 ActionCable:sitepoint.com/…【参考方案2】:

我遇到了确切的问题。我解决它的方法是在用户登录时添加一个cookie,通过SessionsController &lt; Devise::SessionsController。 代码如下所示:

class Users::SessionsController < Devise::SessionsController
  # POST /resource/sign_in
  def create
    super
    cookies[:user_id] = current_user.id
  end
end

您可以通过运行代码从 devise 获取SessionsController

rails generate devise:controllers [scope]

在我的例子中,范围是用户。

【讨论】:

【参考方案3】:

导轨 6:

cookies.encrypted[:user_id]

轨道 5:

cookies.signed[:user_id]

【讨论】:

以上是关于Rails Action Cable:如何授权传入连接?的主要内容,如果未能解决你的问题,请参考以下文章

rails 5 action cable 服务器部署

使用 Nginx、Puma 和 Redis 部署 Rails 5 Action Cable

Ruby on Rails 5 Action Cable:当前模型实例的流(基于 URL 的订阅)

多个订阅的 Action Cable 通知

与 ip 绑定后,Action Cable 不工作

Capybara 不使用 action_cable