不幸的是,对于 websocket 连接,大多数2 websocket 客户端和服务器不支持附加标头和自定义标头1。
所以可能的选择是:
缺点:它可能容易受到攻击,因为它可能最终出现在日志和系统进程信息中,可供有权访问服务器的其他人使用,更多 here
解决方案:加密令牌并附加它,因此即使可以在日志中看到它,在解密之前它也没有任何用处。
客户端:
# Append jwt to protocols
new WebSocket(url, existing_protocols.concat(jwt))
我为 React 和 React-Native 创建了一个 JS 库 action-cable-react-jwt,它就是这样做的。随意使用。
服务器端:
# 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
1 大多数Websocket API(包括Mozilla's)和下面的一样:
WebSocket 构造函数接受一个必需的和一个可选的
参数:
WebSocket WebSocket(
in DOMString url,
in optional DOMString protocols
);
WebSocket WebSocket(
in DOMString url,
in optional DOMString[] protocols
);
url
要连接的 URL;这应该是
WebSocket 服务器会响应。
protocols 可选
单个协议字符串或协议字符串数组。这些
字符串用于指示子协议,以便单个服务器
可以实现多个 WebSocket 子协议(例如,您可能
希望一台服务器能够处理不同类型的交互
取决于指定的协议)。如果您不指定协议
字符串,假定为空字符串。
2 总是有例外,例如,这个 node.js lib ws 允许构建自定义标头,因此您可以使用通常的 Authorization: Bearer token 标头,并在服务器上解析它但是客户端和服务器都应该使用ws。