Ruby on rails WebSocket连接失败:WebSocket握手期间出错:发送非空';Sec WebSocket协议';标题

Ruby on rails WebSocket连接失败:WebSocket握手期间出错:发送非空';Sec WebSocket协议';标题,ruby-on-rails,authentication,websocket,actioncable,Ruby On Rails,Authentication,Websocket,Actioncable,我正在Rails API/React项目中使用ActionCable设置聊天功能,并试图找出验证连接的最佳解决方案 该项目使用Desive jwt gem,因此我的授权作为标题传递。由于Web套接字不允许使用头文件,我一直在寻找最佳的替代方法。我发现的解决方案建议如下之一(附带各种警告): 将JWT作为url中的查询参数发送 劫持HTTP_secu_WEBSOCKET_协议并以这种方式发送 这两种解决方案都感觉不太好,但我尝试使用第二种解决方案,因为在url中发送敏感信息(即使是编码的JWT

我正在Rails API/React项目中使用ActionCable设置聊天功能,并试图找出验证连接的最佳解决方案

该项目使用Desive jwt gem,因此我的授权作为标题传递。由于Web套接字不允许使用头文件,我一直在寻找最佳的替代方法。我发现的解决方案建议如下之一(附带各种警告):

  • 将JWT作为url中的查询参数发送
  • 劫持HTTP_secu_WEBSOCKET_协议并以这种方式发送
这两种解决方案都感觉不太好,但我尝试使用第二种解决方案,因为在url中发送敏感信息(即使是编码的JWT)感觉不太好

以下是my 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
      begin
        jwt = request.env['HTTP_SEC_WEBSOCKET_PROTOCOL']
        decoded_jwt = JWT.decode(jwt, Rails.application.credentials.devise_jwt_secret_key)[0]
        id = decoded_jwt['sub']

        case decoded_jwt['scp']
        when 'admin'
          Admin.where(id: id).first
        when 'hero'
          Hero.where(id: id).first
        when'villain'
          Villain.where(id: id).first
        else
          reject_unauthorized_connection
        end
      rescue
        reject_unauthorized_connection
      end
    end
  end
end

服务器本身似乎没有问题:

Started GET "/cable" for ::1 at 2020-07-22 18:26:02 +0100
Started GET "/cable/" [WebSocket] for ::1 at 2020-07-22 18:26:02 +0100
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
Finished "/cable/" [WebSocket] for ::1 at 2020-07-22 18:26:02 +0100
  Admin Load (0.2ms)  SELECT "admins".* FROM "admins" WHERE "admins"."id" = $1 ORDER BY "admins"."id" ASC LIMIT $2  [["id", 1], ["LIMIT", 1]]
  ↳ app/channels/application_cable/connection.rb:19:in `find_verified_user'
Registered connection (Z2lkOi8vYXBpNTUtbWFpcy9BZG1pbi8x)
这个错误似乎在告诉我,我需要一些关于额外协议的确认或信息,我已经偷偷地将我的JWT放入了这个协议。。。但我不知道该怎么做

任何帮助都将不胜感激!甚至可以用rails ActionCable发送附加协议吗?还是我必须求助于使用查询参数?或者有没有更整洁的方法来解决这个问题


我第一次尝试使用web套接字,所以提前感谢您的帮助

通过
Sec WebSocket协议传递凭据是基于web的应用程序的WebSocket身份验证的常见解决方法,因为浏览器不支持在连接启动时发送自定义头

如果您通过
Sec-WebSocket-Protocol
头传递值,服务器必须将相同的头/值对返回给客户端

由于
Sec-WebSocket-Protocol
头不是用于向WebSocket服务器传递凭据的,因此您必须遵守其规则,将其视为协议并满足其要求

Started GET "/cable" for ::1 at 2020-07-22 18:26:02 +0100
Started GET "/cable/" [WebSocket] for ::1 at 2020-07-22 18:26:02 +0100
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
Finished "/cable/" [WebSocket] for ::1 at 2020-07-22 18:26:02 +0100
  Admin Load (0.2ms)  SELECT "admins".* FROM "admins" WHERE "admins"."id" = $1 ORDER BY "admins"."id" ASC LIMIT $2  [["id", 1], ["LIMIT", 1]]
  ↳ app/channels/application_cable/connection.rb:19:in `find_verified_user'
Registered connection (Z2lkOi8vYXBpNTUtbWFpcy9BZG1pbi8x)