验证ActionCable连接

asi*_*niy 4 ruby ruby-on-rails ruby-on-rails-5 actioncable

我找到了一个很棒的ActionCable宝石,这是SPA的一个很好的解决方案.

我只想要送html,cssjs资产,所有其他连接将通过实施ActionCable.交换字符串或整数并不困难,但我如何通过ActionCable登录?

Pet*_*ett 6

自述文件

# 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

    protected
      def find_verified_user
        if current_user = User.find(cookies.signed[:user_id])
          current_user
        else
          reject_unauthorized_connection
        end
      end
  end
end
Run Code Online (Sandbox Code Playgroud)

所以看起来你可以find_verified_user在这里插入自己的逻辑.该reject_unauthorized_connection方法存在以lib/action_cable/connection/authorization.rb供参考.

来自Heroku:

[authentication]可以通过多种方式完成,因为WebSockets将通过常用于身份验证的标准HTTP头.这意味着您可以使用与WebSocket连接上的Web视图相同的身份验证机制.

由于您无法从JavaScript自定义WebSocket标头,因此您只能使用从浏览器发送的"隐式"身份验证(即基本或cookie).此外,将处理WebSockets的服务器与处理"正常"HTTP请求的服务器完全分开是很常见的.这可能使共享授权标头变得困难或不可能.

考虑到这一点,如果不使用普通的Web登录流来设置您的身份验证cookie,在身份验证步骤之后交付SPA,可能会感到非常痛苦,但希望这可以为您提供一些指导.


ill*_*ist 6

仅供参考,如果您devise已经安装在您的应用程序中,那么您可以使用设置的环境变量warden来查找authenticated user. 对于每个经过身份验证的用户,管理员都将用户对象存储在环境变量中。每个请求都由warden中间件进行身份验证。

注意:这个env不同于ENV.

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

    def connect
      self.current_user = find_verified_user_from_env
    end

    private
    def find_verified_user_from_env
      # extracting `user` from environment var
      current_user = env['warden'].user
      if current_user
        current_user
      else
        reject_unauthorized_connection
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

如果您还没有使用过devise,这里是另一种解决方案。前提是,您必须设置一个user_id在您的sessions_controller或类似名称中调用的签名 cookie 。例如

cookies.signed[:user_id] = current_user.id
Run Code Online (Sandbox Code Playgroud)

和连接:

# 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_from_cookies
    end

    private
    def find_verified_user_from_cookies
      current_user = User.find_by_id(cookies.signed[:user_id])
      if current_user
        current_user
      else
        reject_unauthorized_connection
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)


asi*_*niy -8

解决方案是使用 HTTP 授权令牌。它简单、广泛且明显。这篇文章对我帮助很大