验证 WebSocket 连接
Posted
技术标签:
【中文标题】验证 WebSocket 连接【英文标题】:Authenticating WebSocket Connections 【发布时间】:2017-11-06 19:57:37 【问题描述】:这似乎是一个非常愚蠢的问题,但我最近才接触到 Node.js,需要确保在我的 Laravel 应用程序中发生的相同类型的身份验证发生在 Node.js 中。
显然,我需要使用 API,但我对如何以安全的方式执行此操作感到困惑。我看过这篇文章:
https://www.ida.liu.se/~TDP024/labs/hmacarticle.pdf
并且已经研究过他们的算法来构建 API。但我不明白它是如何安全的。
根据帖子,您将公钥和私钥存储在数据库中。每个人都可以看到公钥,但私钥是私有的。但是,当将其发送到服务器时,您会将私有数据的散列版本与其他数据一起发送到服务器。
这听起来很好。但是,这是否意味着公钥和哈希是公开的,所以私钥也暴露了?
例如,假设我尝试建立以下连接
ws://example.com/pull?public=A89-3NJ2-KAN-NKSN1&hash=QmFzZTY0IHRoZSBoZWxsIG91dCBvZiBtZSBiYWJ5Li4uLi4u
是什么阻止了其他用户共享此链接,让无关的用户访问它?
【问题讨论】:
这能回答你的问题吗? WebSockets authentication 【参考方案1】:您链接到的文章描述了如何验证单个请求,而不是整个会话。也就是说,用户发送公共 api_key
以及一些描述 API 特定请求的 request
数据(例如, "action":"latest_price", "symbol":"GOOG"
用于股票市场 API)。
为了进行身份验证,用户还使用共享 API 访问密钥作为 HMAC
密钥来计算 HMAC(secret, api_key+request)
。如果他们不知道secret
,其他人无法计算这一点。只有用户和服务器应该知道secret
,因为它基本上是用户使用API 的密码。
您描述的情况非常不同:您使用的是 WebSocket,所以我假设您将交互发送请求。如果要对整个套接字会话进行身份验证,则这种方法没有意义,因为它旨在对单个请求进行身份验证。您可以将此方法应用于内部 WebSocket 连接的单个请求。
对于验证新连接(即“哪个登录用户正在打开此连接?”),使用 auth cookie 是合适的,就像您对传统 HTTP 连接所做的那样。
下面,我假设 Web Socket 的目的是只发送一个请求(这真的让我想知道为什么它是一个 WebSocket),所以请求级别的身份验证是有意义的.
是什么阻止其他用户共享此链接,让无关用户访问它?
什么都没有。您是否希望其他人在冒充您的同时提交特定请求?然后无论如何,给他们那个链接并告诉他们使用它。
链接中的凭据包括 API 请求的 HMAC(以及您的身份),只有您作为 API 密钥的唯一所有者才能生成。如果您将该 HMAC 提供给其他人,他们可以提交并冒充您执行该特定请求。但是,它们无法创建更多请求,因为它们没有您的 API 密钥来为不同的请求生成更多 HMAC 值。
事实上,如果您不希望提交该请求,那么您一开始就不应该使用您的秘密来创建身份验证 HMAC!为什么您要对您不打算提交的请求进行身份验证?
【讨论】:
问题在于,通过给另一个人链接,它可以让他们访问打开一个 WebSocket,否则他们将无权进入。这就是我要防止的。 @Shawn31313 所以您希望用户不可能自愿允许其他人冒充他们?这根本是不可能的——如果我想自愿将我证明自己身份的能力赠送给其他人,我可以随时提供我的电子邮件密码或身份验证 cookie。 @Shawn31313 还是只想防止用户意外泄露链接?如果是这种情况,只需使用 cookie 或在套接字通道中发送凭据来传达该信息。 所以正在套接字通道中发送凭据,但仍然无法验证用户是否已登录。 @Shawn31313 如果用户向服务发送验证用户身份的凭据,我不清楚他们没有登录在什么意义上。我不明白不幸的是,你试图阻止的事情。听起来仍然像,“如果有人为用户 X 提供了完美的凭据,但他们实际上不是用户 X,我该如何阻止他们?这对我来说没有意义——这就是凭证的用途。服务器依靠凭证来建立身份;如果这些被盗或被滥用,那超出了服务器的处理能力。【参考方案2】:看看this
基本上
-
使用网站的正常身份验证从浏览器向后端发出“websocket preauth”请求
后端在响应正文中返回一个 CSRF 令牌,并在响应标头中设置一个带有
SameSite=Strict
的“websocket auth”cookie
尝试与后端建立 websocket 连接,并在查询参数中添加 CSRF 令牌
后端检查
websocket auth cookie 和 CSRF 令牌有效
Origin
标头的值与已批准的域匹配
后端发送响应并升级连接以使用 websockets
【讨论】:
以上是关于验证 WebSocket 连接的主要内容,如果未能解决你的问题,请参考以下文章
由于 BoringSSL 证书验证失败,iOS 上的安全 websocket 连接失败