简体   繁体   English

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

[英]Rails Action Cable: How to authorize incoming connection?

I am trying to implement authorization on the websocket connection (rails 5.2.1)我正在尝试在 websocket 连接上实现授权(rails 5.2.1)

Following the rubyonrails guideline , I have created the connection.rb as follows:按照rubyonrails 指南,我创建了 connection.rb 如下:

# app/channels/application_cable/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

Unfortunately, all the websocket connection requests are rejected.不幸的是,所有的 websocket 连接请求都被拒绝了。 (I have figured out that cookies.encrypted[:user_id] is returning nil.) (我发现 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

Would you please guide me how I can access current user info within app/channels/application_cable/connection.rb?请指导我如何在 app/channels/application_cable/connection.rb 中访问当前用户信息?

In order to get current_user from Devise, you need to change your connection.rb as follows:为了从 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

I faced the exact problem.我遇到了确切的问题。 The way I solved it was by adding a cookie when the user signed in, through SessionsController < Devise::SessionsController .我解决它的方法是在用户登录时通过SessionsController < Devise::SessionsController添加一个 cookie。 The code looks like this:代码如下所示:

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

You can get the SessionsController from devise by running the code:您可以通过运行以下代码从设计中获取SessionsController

rails generate devise:controllers [scope]

In my case the scope was users.在我的情况下,范围是用户。

Rails 6:导轨 6:

cookies.encrypted[:user_id]

Rails 5:导轨 5:

cookies.signed[:user_id]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM