How do I get current_user in ActionCable rails-5-api app?

我们两清 提交于 2019-11-30 11:39:12
Sajan

If you see the doc you provided, you will know that identified_by is not a method for a Channel instance. It is a method for Actioncable::Connection. From Rails guide for Actioncable Overview, this is how a Connection class looks like:

#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 current_user = User.find_by(id: cookies.signed[:user_id])
          current_user
        else
          reject_unauthorized_connection
        end
      end
  end
end

As you can see, current_user is not available here. Instead, you have to create a current_user here in connection.

The websocket server doesn't have a session, but it can read the same cookies as the main app. So I guess, you need to save cookie after authentication.

if u are using devise gems in rails, Please replace this function:

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

I hope this will help u.

Well, in theory:

  • You have access to the cookies in the ActiveCable::Connection class.
  • You can set and receive cookies.signed and cookies.encrypted
  • Both the application and ActionCable share same configuration, therefore they share same `secret_key_base'

So, if you know the name of your session cookie (somehow obvious, let it be called "_session"), you can simply receive the data in it by:

cookies.encrypted['_session']

So, you should be able to do something like:

user_id = cookies.encrypted['_session']['user_id']

This depends on do you use cookie store for the session and on the exact authentication approach, but in any case the data you need should be there.

I found this approach more convenient as the session is already managed by the authentication solution you use and you more likely don't need to care about things like cookie expiration and duplication of the authentication logic.

Here is more complete example:

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

    def connect
      session = cookies.encrypted['_session']
      user_id = session['user_id'] if session.present?

      self.current_user = (user_id.present? && User.find_by(id: user_id))

      reject_unauthorized_connection unless current_user
    end
  end
end

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!