Firebase Firestore:自定义管理员访问权限

sin*_*enm 10 rules admin firebase access google-cloud-firestore

在火力地堡公司的FireStore,我想只允许(自定义设定),管理员写/更新/删除资源,为此,我已经得到了这些安全规则:

service cloud.firestore {
  match /databases/{database}/documents {
    match /resources {
      allow read;
      allow write, update, delete: if get(/users/$(request.auth.uid).isAdmin);
    }
    match /resources/{resource} {
      allow read;
      allow write, update, delete: if get(/users/$(request.auth.uid).isAdmin);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我正在使用在users集合中标记为admin的用户登录:

用户集合只有一个管理员

NfwIQAjfNdS85yDvd5yPVDyMTUj2是从身份验证窗格获取的UID:

用户存在

但是,出于某种原因(更新:确定原因;请参阅答案),在确定我已经使用admin用户登录后,在写入资源集合时,我收到了PERMISSION_DENIED错误.

也许可以从Firestore查看请求日志?然后,我可以看看request.auth.uid与我的收藏和规则相匹配的内容.

sin*_*enm 13

在写我的问题时,我让它成功了!我犯了两个错误,如果我正确阅读文档,这两个错误都可以避免.

首先,对服务定义函数的 所有调用都get需要在路径前加上/ databases/$(database)/ documents /.所以这个规则:

allow write: if get(/users/$(request.auth.uid)).isAdmin;
Run Code Online (Sandbox Code Playgroud)

成为这个:

allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).isAdmin;
Run Code Online (Sandbox Code Playgroud)

我知道,这很长,但事实就是如此.我不确定为什么Firestore本身无法做到这一点,因为看到相同的路径前缀在所有调用中保持不变get,但也许这是为了未来尚未准备好的某些功能,例如跨数据库查询或其他什么.

其次,该get函数将返回一个资源,而您又需要调用.data它来获取它包含的实际数据.因此,而不是这样做:

get(/path/to/user/).isAdmin
Run Code Online (Sandbox Code Playgroud)

你需要这样做:

get(/path/to/user/).data.isAdmin
Run Code Online (Sandbox Code Playgroud)

现在我只希望我能够将该逻辑提取到用户定义的函数中:

function isAdmin() {
  return get(/databases/$(database)/documents/users/$(request.auth.uid)).data.isAdmin;
}
Run Code Online (Sandbox Code Playgroud)

但这样做会再次导致PERMISSION_DENIED,并且在不知道函数中实际发生了什么的情况下,我不确定我是否会花更多的时间来尝试解决这个问题.

更新: @Hareesh 指出函数必须在匹配器的范围内定义,因此可以将函数放在默认的顶级匹配器中,如下所示:

service cloud.firestore {
  match /databases/{database}/documents {
    function isAdmin() {
      return get(/databases/$(database)/documents/users/$(request.auth.uid)).data.isAdmin == true;
    }

    // ...
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 对于采用这种方法的任何人,请注意,如果您向用户提供写入权限以写入他们自己的用户文档“/users/${userId}”,精明的敏锐用户可以将属性“isAdmin”设置为 True,并且将被视为管理员。为了防止这种情况,您可以创建一条安全规则来拒绝对用户文档使用“isAdmin”进行写入请求,或者将该“isAdmin”属性保留在用户没有写入权限的单独 Firestore 文档中。 (3认同)