【问题标题】:Firestore - security rules for users within companiesFirestore - 公司内用户的安全规则
【发布时间】:2018-08-17 10:24:01
【问题描述】:

我们当前的 Firestore 结构如下:

  • 目前我们没有使用任何子集合
  • 用户拥有他们所属公司的列表
  • 每个项目仅与 1 家公司相关
  • 项目属于一家公司,当在 companyId 字段中写入该公司 UID 时

我的第一个问题是我们如何指定这个数据库定义的安全规则?是否有一些最佳实践方法?

我们的第一个想法是这样做:

match /databases/{database}/documents/projects/{projectUid}/{document=**} {
allow read: if 
(/databases/$(database)/documents/projects/$(projectUid)/companyId) === 
(/databases/$(database)/documents/users/$(request.auth.uid)/companyId)
}

但是根据文档,这意味着每次读取基本上需要 3 次读取(2 次安全查询和 1 次从数据库中实际读取)。这似乎是在浪费查询。

还有比这更好的方法吗? 我们正在考虑改为子集合:

  • 最后,我们将在根集合中拥有“公司”和“用户”(用于存储所有用户详细信息)
  • 项目将是公司的子集合
  • 页面将是项目的子集合
  • ...等
  • 并且公司将包含用户列表(而不是像现在这样相反) - 但只有列表,而不是用户详细信息

这样我们可以使用与文档类似的方法,其中每个匹配项都包含 {companyId} 并且在允许语句中我们将使用类似

match /databases/{database}/documents/companies/{companyId}/projects/{projectId} {
    allow read: if
    exists(/databases/$(database)/documents/companies/$(companyId)/users/$(request.auth.uid));
}

感谢您就如何以最可扩展且尤其是最安全的方式构建它的任何建议。

【问题讨论】:

    标签: firebase google-cloud-firestore firebase-security


    【解决方案1】:

    你考虑过adding a user's company ID as a custom claim to their profile吗?这样,您的安全规则就不需要额外读取。

    由于设置这些声明需要 Admin SDK,因此需要您可以在某处运行受信任的代码。但是,如果您还没有自己的可信环境,您可以使用 Cloud Functions,例如基于其他一些操作,例如写入您当前的 Firestore 结构。

    【讨论】:

    • 我一开始就考虑过它,但在它看起来像是非常复杂的任务之前(我将它与自定义身份验证的自定义令牌生成混合在一起,这是我根本不想要的)。在检查了它现在是如何工作的之后,这似乎是一个不错的解决方案(此外,我还将获得对存储的控制权)。谢谢!
    【解决方案2】:

    向弗兰克添加答案。

    从其他 API SDK(例如 microsoft graph)借用,通常要发出资源请求,您首先使用代表用户范围/权限的身份验证令牌初始化 Client 对象。例如:

    const client = new SDKClient(my_auth_token);
    

    客户端构造函数将对声明进行令牌验证步骤。然后,您可以进行 REST 调用,例如

    const response = await client.someEndpoint({ method: 'POST', body: my_object });
    

    我建议您使用常规的 firebase nodejs 客户端,而不是使用管理 SDK 来读取/写入您的 Firestore。要使用安全规则限制访问,请将 Firebase JWT 令牌传递到此自定义 SDKClient 类中,并使用您从请求标头中获取的令牌。在构造函数中,初始化一个新的 firebase 'app'。因为常规的 Firebase 客户端是
    根据安全规则,这将满足您的需求。 this answer 中已经提供了一些示例代码。

    我应该根据这个firebase doc 补充一点,有一个使用 admin-sdk 服务器端的“警告”,但我不确定我明白为什么。

    【讨论】:

      【解决方案3】:

      对于我们正在研究的类似事情,我已经想到了一种方法,即只有某些用户可以访问的私人聊天室,是使用服务器上的密钥加密所有消息,并且只授予读取权限某些用户的关键。这样,额外的读取只需要发生一次,就在第一次获取密钥时,然后没有额外安全规则的正常读取就可以了,因为攻击者无法对它们做任何事情,因为它们是加密的他们无权访问密钥。

      【讨论】:

        猜你喜欢
        • 2019-09-15
        • 2018-10-19
        • 2019-07-05
        • 1970-01-01
        • 2020-06-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多