如何在ActionCable rails-5-api应用程序中获取current_user?

时间:2017-02-25 04:15:58

标签: ruby-on-rails authentication actioncable

为什么我无法在渠道中检索main.o或如何检索main.o: main.cpp recipe $(objects): %.o: %.cpp functions.h recipe

我该使用什么?

  • Rails 5.0.1 --api (我没有任何意见NOR使用咖啡)
  • 我使用react-native app来测试 (无需授权即可正常工作)
  • 我不使用设计用于验证 (我使用JWT而不是使用Knock ,所以没有cookie)

尝试在rubydoc.info

中描述的ActionCable频道中获取current_user

代码看起来像

current_user

运行它,我收到此错误:

current_user

如果我删除class MessageChannel < ApplicationCable::Channel identified_by :current_user def subscribed stream_from 'message_' + find_current_user_privileges end def unsubscribed # Any cleanup needed when channel is unsubscribed end protected def find_current_user_privileges if current_user.has_role? :admin 'admin' else 'user_' + current_user.id end end end ,我会

[NoMethodError - undefined method `identified_by' for MessageChannel:Class]

5 个答案:

答案 0 :(得分:4)

如果您看到自己提供的文档,则会发现identified_by不是Channel实例的方法。这是Actioncable::Connection的一种方法。 从Rails操作系列概述指南,这是Connection类的外观:

#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

如您所见,此处无法使用current_user。相反,您必须在此处创建current_user

websocket服务器没有会话,但它可以读取与主应用程序相同的cookie。所以我想,你需要在认证后保存cookie。

答案 1 :(得分:2)

self.current_user中设置ApplicationCable::Connection后,它在通道实例中变为可用。 因此,您可以像Sajan所写的那样设置身份验证,只需在current_user

中使用MessageChannel

例如,这段代码对我有用

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

    def connect
      self.verified_user = find_verified_user
    end

    private

    def current_user
      jwt = cookies.signed[:jwt]
      return unless jwt

      decoded = JwtDecodingService.new(jwt).decrypt!
      @current_user ||= User.find(decoded['sub']['user_id'])
    end

    def find_verified_user
      current_user || reject_unauthorized_connection
    end
  end
end

class NextFeaturedPlaylistChannel < ApplicationCable::Channel
  def subscribed
    stream_from "next_featured_playlist_#{verified_user.id}"
  end
end

答案 2 :(得分:1)

如果您在rails中使用devise gem,请替换此功能:

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

我希望这对您有帮助。

答案 3 :(得分:1)

对于Rails 5 API模式:

application_controller.rb

class ApplicationController < ActionController::API
   include ActionController::Cookies
   ...
   token = request.headers["Authorization"].to_s
   user = User.find_by(authentication_token: token)
   cookies.signed[:user_id] = user.try(:id)

connection.rb

class Connection < ActionCable::Connection::Base
   include ActionController::Cookies
   ...
   if cookies.signed[:user_id] && current_user = User.where(id: cookies.signed[:user_id]).last
     current_user
   else
     reject_unauthorized_connection
   end

config / application.rb

config.middleware.use ActionDispatch::Cookies

答案 4 :(得分:0)

从理论上讲:

  • 您可以访问ActiveCable::Connection类中的cookie。
  • 您可以设置和接收cookies.signedcookies.encrypted
  • 应用程序和ActionCable共享相同的配置,因此它们共享相同的“ secret_key_base”

因此,如果您知道会话cookie的名称(某种程度上很明显,将其称为“ _session”),则可以通过以下方式简单地接收其中的数据:

cookies.encrypted['_session']

因此,您应该可以执行以下操作:

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

这取决于您是否在会话中使用cookie存储以及确切的身份验证方法,但是在任何情况下,所需的数据都应该存在。

我发现这种方法更方便,因为会话已经由您使用的身份验证解决方案进行管理,并且您很可能不必担心Cookie过期和身份验证逻辑重复之类的事情。

以下是更完整的示例:

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