alx*_*bra 16 ruby-on-rails-5 actioncable
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user
def connect
#puts params[:auth_token]
self.current_user = find_verified_user
logger.add_tags 'ActionCable', current_user.name
end
end
end
Run Code Online (Sandbox Code Playgroud)
我不使用web作为动作电缆的终点,所以我想使用auth_token进行身份验证.默认情况下,操作电缆使用会话用户标识进行验证 如何通过params连接方法?
小智 43
我设法将我的身份验证令牌作为查询参数发送.
在我的javascript应用程序中创建我的消费者时,我将在有线服务器URL中传递令牌,如下所示:
wss://myapp.com/cable?token=1234
Run Code Online (Sandbox Code Playgroud)
在我的有线连接中,我可以token通过访问request.params:
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user
def connect
self.current_user = find_verified_user
logger.add_tags 'ActionCable', current_user.name
end
protected:
def find_verified_user
if current_user = User.find_by(token: request.params[:token])
current_user
else
reject_unauthorized_connection
end
end
end
end
Run Code Online (Sandbox Code Playgroud)
它显然不理想,但我不认为你可以在创建websocket时发送自定义标题.
Yuv*_*rmi 15
皮埃尔的回答是有效的.但是,明确在应用程序中期望这些参数是个好主意.
例如,在你的配置文件之一(例如application.rb,development.rb等...),你可以这样做:
config.action_cable.mount_path = '/cable/:token'
Run Code Online (Sandbox Code Playgroud)
然后只需从您的Connection班级访问它:
request.params[:token]
Run Code Online (Sandbox Code Playgroud)
不幸的是,WebSocket连接,其他标头和自定义的,不支持1通过最2个的WebSocket客户端和服务器.所以可能的选择是:
作为URL参数附加并在服务器上解析它
path.to.api/cable?token=1234
# and parse it like
request.params[:token]
Run Code Online (Sandbox Code Playgroud)缺点:它可能是易受攻击的,因为它可能最终出现在有权访问服务器的其他人的日志和系统进程信息中,更多信息
解决方案:加密令牌并将其附加,因此即使可以在日志中看到它,在解密之前它也没有用处.
客户端:
# Append jwt to protocols
new WebSocket(url, existing_protocols.concat(jwt))
Run Code Online (Sandbox Code Playgroud)
我创建了一个JS库行动索反应,智威汤逊的React和React-Native,只是做到这一点.随意使用它.
服务器端:
# get the user by
# self.current_user = find_verified_user
def find_verified_user
begin
header_array = self.request.headers[:HTTP_SEC_WEBSOCKET_PROTOCOL].split(',')
token = header_array[header_array.length-1]
decoded_token = JWT.decode token, Rails.application.secrets.secret_key_base, true, { :algorithm => 'HS256' }
if (current_user = User.find((decoded_token[0])['sub']))
current_user
else
reject_unauthorized_connection
end
rescue
reject_unauthorized_connection
end
end
Run Code Online (Sandbox Code Playgroud)
1大多数Websocket API(包括Mozilla)都如下所示:
WebSocket构造函数接受一个必需参数和一个可选参数:
Run Code Online (Sandbox Code Playgroud)WebSocket WebSocket( in DOMString url, in optional DOMString protocols ); WebSocket WebSocket( in DOMString url, in optional DOMString[] protocols );
url要连接的URL; 这应该是WebSocket服务器将响应的URL.
protocols可选的单个协议字符串或协议字符串数组.这些字符串用于指示子协议,因此单个服务器可以实现多个WebSocket子协议(例如,您可能希望一个服务器能够根据指定的协议处理不同类型的交互).如果未指定协议字符串,则假定为空字符串.
2总有一些消息,例如,这个node.js lib ws允许构建自定义头,因此你可以使用通常的Authorization: Bearer token头,并在服务器上解析它,但客户端和服务器都应该使用ws.
正如我在评论中已经指出的,接受的答案不是一个好主意,只是因为约定是 URL 不应包含此类敏感数据。您可以在此处找到更多信息:https : //tools.ietf.org/html/rfc6750#section-5.3(尽管这是专门针对 OAuth 的)。
然而,还有另一种方法:通过 ws url 使用 HTTP 基本身份验证。我发现,大多数的WebSocket客户端允许您通过预先网址为http这样的基本身份验证隐式设置标题:wss://user:pass@yourdomain.com/cable。
这将添加Authorization值为的标头Basic ...。在我来说,我是用色器件与色器件,智威汤逊和简单地实现从其中拉JWT出的宝石提供的一个继承的策略Authorization头。所以我像这样设置 url:wss://TOKEN@host.com/cable将标题设置为 this (pseudo):Basic base64("token:")并在策略中解析它。
| 归档时间: |
|
| 查看次数: |
7400 次 |
| 最近记录: |