【发布时间】:2020-05-11 19:22:47
【问题描述】:
我正在开发一个使用无服务器框架构建后端的项目。最近,我添加了一个使用 API Gateway 的 websockets 的功能。但是,我对我的特定实现的安全性表示怀疑,并想问一下它们的有效性。
我努力在我的 websocket 路由中构建身份验证。有一个授权功能,但不幸的是,原生 Javascript API 无法编辑 Websocket 消息中的标头 - 这意味着我必须在 url 参数中提交授权令牌,而我不希望这样做。
我想出了一个解决方法。我在 API Gateway 上使用无服务器设置了现有的 HTTP 微服务,并通过 AWS Cognito Identity Federation 进行了身份验证。我的解决方案是将我的 websocket 身份验证“搭载”到我的 HTTP 服务上,如下所示。
- 我的客户端打开一个 websocket 连接,并收到 API 网关分配给它的 connectionId。
- 我的客户端使用 connectionId 调用 HTTP 路由,该路由已通过 Cognito 进行身份验证。这有助于让我的后端知道这个特定的 connectionId 已经过身份验证。我将 connectionId 和 Cognito 身份以及其他信息推送到数据库。这样,以后我可以找到与特定 Cognito 身份相关联的 connectionId。
- 当客户端想要调用“安全”的 websocket 方法时,websocket 方法会检查查找表以查看该 connectionId 是否与正确的 Cognito 身份相关联。如果是,则该方法通过。否则,连接将关闭。
我在 Heroku 上找到了这个关于 websocket 安全的资源,它推荐了一个类似但不完全相同的过程:https://devcenter.heroku.com/articles/websocket-security
建议如下:
“因此,我们看到的一种似乎很好地解决了 WebSocket 身份验证问题的模式是基于“票证”的身份验证系统。广义上讲,它的工作原理如下:
当客户端代码决定打开 WebSocket 时,它会联系 HTTP 服务器以获取授权“票证”。
服务器生成此票证。它通常包含某种用户/帐户 ID、请求票证的客户端的 IP、时间戳和任何其他类型的内部记录
保持你可能需要。服务器存储此票证(即在数据库或缓存中),并将其返回给客户端。
客户端打开 WebSocket 连接,并将此“票证”作为初始握手的一部分发送。
然后,服务器可以比较这张票,检查源 IP,验证票没有被重复使用并且没有过期,并进行任何其他类型的权限检查。如果一切顺利,WebSocket 连接现在已经验证完毕。”
据我所知,我的方法与 heroku 的相似之处在于它们都使用 HTTP 方法进行身份验证,但不同之处在于
1) Heroku 的方法在打开时检查身份验证,而我的方法在打开后检查 2) Heroku 的方法需要生成和存储安全令牌
我不想通过 websocket 发送授权,因为我必须将它存储在 url 参数中,而且我也不想生成和存储令牌,所以我采用了我的方法。
但是,我对我的方法也有一些疑问。
1) 因为我不检查 websocket 打开的授权,所以理论上这种方法容易受到 dDos 攻击,攻击者只需打开尽可能多的套接字。我在这里的假设是,API Gateway 有责任通过其 Leaky Bucket 算法进行预防。
2) 我的策略取决于 connectionId 是否安全。如果攻击者能够欺骗此 connectionId,那么我的策略将不再有效。我假设这个 connectionId 在 API Gateway 内部发出以标记特定的连接,因此不应受到攻击。但是,我想仔细检查是否是这种情况。
【问题讨论】:
标签: amazon-web-services security websocket aws-api-gateway serverless