验证 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 连接的主要内容,如果未能解决你的问题,请参考以下文章

验证 WebSocket 连接

由于 BoringSSL 证书验证失败,iOS 上的安全 websocket 连接失败

通过 HTTP 中间件验证 WebSocket 连接 - Golang

使用nodejs创建加入用户验证的websocket服务

开放的 websocket 连接都有哪些安全问题?

是否可以对 websocket 升级请求使用不记名身份验证?