Ruby on rails WebSocket连接失败:WebSocket握手期间出错:发送非空';Sec WebSocket协议';标题
我正在Rails API/React项目中使用ActionCable设置聊天功能,并试图找出验证连接的最佳解决方案 该项目使用Desive jwt gem,因此我的授权作为标题传递。由于Web套接字不允许使用头文件,我一直在寻找最佳的替代方法。我发现的解决方案建议如下之一(附带各种警告):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
- 将JWT作为url中的查询参数发送
- 劫持HTTP_secu_WEBSOCKET_协议并以这种方式发送
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)