从多租户SPA保护对DocumentDB的访问

时间:2016-08-02 09:50:36

标签: security authentication authorization azure-cosmosdb

我们正在开发使用Azure DocumentDb作为存储的多租户Angular Web App。来自应用程序的所有租户的文档存储在同一集合中,并通过文档的tenantId属性进行区分。我们将拥有中间层.NET服务,其中包含DocumentDb的主密钥,并为Web App公开CRUD操作的REST API端点。 Web应用程序的用户由oAuth提供商(Google,Facebook,Microsoft)进行身份验证。保护租户数据的最佳做法是什么,因此一个租户的用户无法访问其他租户的数据?

2 个答案:

答案 0 :(得分:2)

这可以通过在读取和写入中逻辑拦截中间层中的请求,以及在每个文档中保留tenantId标记来实现。

让我们从读取路径开始。假设每个文档都将tenantId属性设置为文档所属的用户的相应租户。要读取任何数据,请通过参数化SQL查询(https://azure.microsoft.com/en-us/blog/announcing-sql-parameterization-in-documentdb/)并始终确保查询具有tenantId过滤器。这将确保用户的请求仅处理请求应该查看的租户ID。参数化对于避免注入以及访问其他租户的数据非常重要。

在写入路径上,您需要确保每个文档都正确设置了tenantId属性。如果最终客户端没有设置,或者即使它没有设置,中间层应解析此并确保它与您从OAuth提供商返回的用户授权令牌对应的租户匹配。

在此上下文中,请注意tenantId的分区键有助于将单个租户的所有数据保存在一起。只要查询具有tenantId过滤器,这对于在单个分区上进行归零有效的查询很有帮助。

答案 1 :(得分:1)

我没有足够的信心将其称为最佳做法,但我们有一个像您一样的中间层REST API,这里是我们的工作:

  1. 客户端(甚至是浏览器代码)可以提交任意查询。我们使用sql-from-mongo,因此这些是类似mongo的语法,javascript客户端更容易构建查询,但我建议使用原始SQL查询同样安全,只要参数化变量和你不允许SELECT条款中的任何预测。我们在sql-from-mongo翻译中完成的最后一部分,但您可以删除预测(用SELECT替换提供的SELECT *子句)或拒绝任何不以#{1}}开头的查询SELECT *。这是至关重要的,因为如果没有它,不良演员可以投射他们自己的tenentIDuserID其余的这些控制键。

  2. 我们的REST中间件为每个客户端缓存租户和用户上下文,其中包含我们的授权规范(概念与Firebase类似)。在最简单的形式中,用户与一个tenent绑定,并且该用户对该租户的所有数据具有读取权限,但您可以指定任何内容。

  3. 执行查询时,将根据授权规范检查返回的数据集。根据具体情况,任何数量的不允许文件的请求将被完全拒绝,或者不允许的文件会从我们返回的结果集中过滤掉。

  4. 在写作方面,我们做了类似的事情。我们会根据授权规范检查更新,并拒绝任何不符合规定的内容。它比这更复杂,因为我们为所有写操作使用了一个sproc,我们有一个类似mongo的语法用于就地更新,我们为所有写操作实现跨文档ACID(使用sproc) ,但你可以做我没有提出的建议。

  5. 希望这会有所帮助。请随意在评论中提问。