【问题标题】:Firestore Rules: validate data does not have fieldFirestore 规则:验证数据没有字段
【发布时间】:2019-02-15 03:33:22
【问题描述】:

所以我目前对所有用户都有两个角色:isAdmin 和 isReader。

允许管理员读取和写入数据,并且允许读取器读取数据。

当有人创建帐户时,他没有任何权利。甚至没有isReader。只有管​​理员可以更改规则。

这就是我计划的方式:

一旦有人创建了帐户,我就会在 Users 集合中创建一个文档,如下所示:

uid: user.uid,
email: user.email,
role: {
    isAdmin: false,
    isReader: false,
}

每次登录时,我都会更新“电子邮件”和uid,但保持role 不变。为了保护这种行为,我有这些规则:

match /Users/{userId} {
  allow read: if isOwner(userId) || isAdmin();
  allow create: if request.resource.data.hasAll(['uid', 'email', 'role']) && request.resource.data.role.isAdmin == false && request.resource.data.role.isReader == false;
  allow update: if resource.data.role == null || isAdmin();
}

function isAdmin() {
  return getUserData().role.isAdmin == true;
}

我认为我有 2 个错误:

  1. 由于某种原因,data.hasAll(['uid', 'email', 'role']) 不起作用。当我删除这部分时,create 规则按计划工作。

  2. resource.data.role == null 不起作用。我打算检查数据是否包含role 的任何更新,因为我不能允许它不是来自管理员。但由于某种原因,它不起作用。

任何想法我做错了什么?还有我的策略是保存还是有人可以“破解”自己的读者或管理员权限?

【问题讨论】:

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


    【解决方案1】:

    这看起来可能是自定义身份验证声明的一个很好的用例。您可以在安全环境中为用户设置特定角色,如this codelab 所示。下面是在您的服务器中设置自定义声明的示例。您甚至可以为此使用 Cloud Functions。我建议您查看 Codelab 的完整代码,以便了解如何确保不只是任何人都可以请求将自定义声明添加到他们的用户。

    admin.auth().setCustomUserClaims(uid, {Admin: true}).then(() => {
    // The new custom claims will propagate to the user's ID token the
    // next time a new one is issued.
    });
    

    然后您可以在您的安全规则中检查用户的这些角色。

    service cloud.firestore {
      match /databases/{database}/documents {
        match /Users/{userId} {
          allow read: if request.auth.token.Owner == true || request.auth.token.Admin == true;
          allow create: request.auth.uid == userId && 
          request.resource.data.uid == request.auth.uid &&
          request.resource.data.email != null;
          allow update: request.auth.uid == userId || request.auth.token.Admin == true;
        }
      }
    }
    

    请注意,所有关于“角色”的规则都已被删除,因为它们不再需要。如果您对实施有任何疑问,请告诉我,因为这是一个常见问题,我正在尝试围绕此制作更多内容。

    【讨论】:

    • 谢谢珍!我会检查一下。我还没有真正用云功能做过任何事情,也没有用 admin sdk 做过任何事情,但是当我设置了我的基本功能时,我会尝试它。
    • 这是一个很好的解决方案。它减少了在规则中的查找,因为角色来自 Auth 令牌(即不需要 getUserData()),并且它允许跨服务(RTDB、Firestore、存储等)使用角色。
    【解决方案2】:

    request.resource.data.hasAll(['uid', 'email', 'role']) 不起作用,因为 request.resource.dataMap 而不是 List。您应该使用keys()Map 创建一个List 并确保某些键存在。

    关于你的第二个问题,你应该检查是否有写到rolesallow update: if !('roles' in request.writeFields) || isAdmin();。这将确保对roles 的任何更新都将失败,除非用户是管理员。

    关于您的安全问题;我看到几个问题。首先是任何人都可以创建无限的用户,这也意味着任何管理员都可以创建无限的其他管理员帐户。为了阻止这种情况发生,我将在allow create 中添加另一个部分,以限制用户创建:

    allow create: if userId == request.resource.data.uid
      && request.auth.uid == request.resource.data.uid
      && request.resource.data.hasAll(['uid', 'email', 'role'])
      && request.resource.data.role.isAdmin == false
      && request.resource.data.role.isReader == false;`
    

    第二个是任何人都可以更改他们的uid 并尝试冒充他人。显然,这不会改变与他们的 Auth Token 关联的uid,但取决于你如何编写其余规则、后端安全性甚至前端显示,有人可能会利用该缺陷来利用你的代码或其他用户(可能是管理员)。您可以通过检查writeFields 中是否有人更改他们的uid 来确保没有人更改它(您还需要以前的安全解决方案来确保他们在创建过程中不会冒充)。 p>

    allow update: if !('uid' in request.writeFields)
      && (!('roles' in request.writeFields) || isAdmin());
    

    我希望这会有所帮助。

    【讨论】:

    • 感谢您的帮助!添加keys()为我解决了第一个问题,但if !('role' in request.writeFields);似乎对我不起作用。它允许编辑role 字段。我也尝试过if !('role' in request.resource.writeFields);,但这每次都会引发错误(当我更新没有角色字段的用户数据时也是如此)。
    • 对于安全问题:通常我认为当我允许任何管理员提升无限其他人为管理员时很好,因为该程序是为我可以信任管理员的企业而设计的。我不确定我是否 100% 理解您的第一个建议,但我认为附加规则不会禁止我特别需要的任何内容,所以我将添加它们...
    • 我也不确定第二条规则是否适用于我。正如您所说,AuthToken 的 uid 仍然相同,即使他们在“客户端”具有管理员权限,firestore 规则也应该使用 auth uid 保护权限。我目前正在每次登录时更新用户数据的 uid 和电子邮件。这不适用于 2. 建议。但是我认为我不需要在每次登录时更新 uid 和电子邮件,所以我也会测试你的建议。
    • @Jonas 我明白为什么它不适合你。它正在检查“role”而不是“role”、“role.isAdmin”和“role.isReader”。试试!request.writeFields.hasAny(['role','role.isAdmin','role.isReader'])。关于您的第二条评论,管理员(以及其他任何人;包括未登录的人)不仅可以宣传任何人,而且可以随意创建假用户。但是,只有管理员可以授予他们管理员权限,然后可以使用这些权限绕过您可能拥有的任何操作日志系统(即,一种指责管理员滥用行为的方式)。
    猜你喜欢
    • 2020-01-21
    • 2021-07-23
    • 1970-01-01
    • 1970-01-01
    • 2021-07-05
    • 2019-04-26
    • 2020-09-28
    • 2019-02-27
    相关资源
    最近更新 更多