【问题标题】:Trying to set up Cloud Firestore security rules using request.path尝试使用 request.path 设置 Cloud Firestore 安全规则
【发布时间】:2017-11-13 23:41:21
【问题描述】:

我正在努力理解一些 Firestore 安全概念。我想根据request.path 属性设置规则。

我的规则是这样的:

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.path[0]=='appUsers';
    }
  }
}

...然后我使用AngularFire2 添加这样的文档...

this.myAngularFirestore.doc('/appUsers/'+this.auth.auth.currentUser.uid).set({name: this.auth.auth.currentUser.displayName})
      .then(()=>console.log('Added user'))
      .catch(err=>console.log('Could not add user:', err.message));

我认为这应该很简单 based on the docs 但我得到的只是错误 - Missing or insufficient permissions

我知道我已正确登录,如果我使用allow read,write: if true; 打开安全性,我知道查询有效,那么我在这里没有得到什么? request.path[0] 不应该在此处计算为字符串appUsers 从而允许写入数据吗?

任何想法都欣然接受,因为到目前为止我觉得这些规则一起出去并不有趣。

祝大家好运

【问题讨论】:

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


    【解决方案1】:

    我建议使用这个的内置路径匹配器版本:

    service cloud.firestore {
      match /databases/{database}/documents {
        match /appUsers {
          allow read, write;
        }
      }
    }
    

    或者,如果你真的想在条件中指定:

    service cloud.firestore {
      match /databases/{database}/documents {
        match /{pathSegment} {
          allow read, write: if pathSegment == "appUsers";
        }
      }
    }
    

    request.path 是完整路径(例如/projects/<projectId>/databases/(default)/documents/appUsers,这意味着您实际上需要request.path[5](因此我们提供了更简单、更易读的方法)。

    编辑(4/2/18):request.path 支持ListMap 访问:

    • List: request.path[5] == "appUsers"
    • Map: request.path['pathSegment'] == "appUsers",但请注意它仅适用于通配符(例如{name})值

    【讨论】:

    • 这很有道理,但它似乎对我不起作用??我已经建立了一个新的 Firebase 项目和 Firestore 数据库,一个新的 Angular 项目(使用 CLI),安装并初始化了 AngularFire2 并尽可能地简化了查询,但唯一能让我成功编写的规则是match /{segment=**} {allow read, write;}。我尝试了您的示例,但得到了相同的权限错误。有什么方法可以调试规则或查看请求失败的原因吗?
    • 所以,我对request.path 一点也不走运——无论我如何表达它都失败了——但正如你所说,这里没有必要,你的第二个例子最终让我明白了。我觉得我在这里学到了一些东西,但我无法真正解释什么 - 事情在我的脑海中更清晰了,所以谢谢你:)
    • @MikeMcDonald request.path[n] 永远不会为我工作。我正在尝试通过 'request.auth.uid==request.path[10]' 检查当前用户是否具有与路径相同的 uid,其中 10 的计算方式与示例相同。我什至检查了 10 以外的位置,但它仍然无法正常工作。我还通过在开头添加“/”到“request.auth.uid”进行检查,认为路径可能在开头有“/”,但它仍然无法正常工作。可能是什么问题?
    • @KartikWatwani 简短的回答是我很笨,而且我没有正确记录它。我们目前不提供索引查找,但我们现在正在添加它们。我会尽快修复文档(以及他的行为)!
    • @MandisaW 当前行为提取命名段,因此:/{foo}/{bar}/{baz} 将允许request.path['foo'] == someValue,但不允许request.path[1] == someValue。代码刚刚提交,所以我希望它会在下一次推出时投入生产(也许下周?)。准备好后,我会用信息更新线程。
    【解决方案2】:

    Mike McDonald 回答者帮助我创建了一个规则,该规则将允许读取所有表,除非集合名称位于“hasReadRules”数组中(通用允许读取语句阻止我覆盖某些表的读取规则,因为如果您在某处允许读取为真,它将覆盖您在任何其他规则中的任何允许读取错误):

    // allow read for all collection that are not in the hadReadRules array
    match /{pathSegment}/{document=**} {
      allow read: if !(pathSegment in hasReadRules());
      allow write: if false;
    }
    // these collection will have their own read rules
    function hasReadRules() {
        return ["calculations", "users", "push_notifications"];
    }
    
    // below is an example where i want to override the allow
    //read rule for a single collection without having to create a read rule for every collection
    // If we do this without using the hadReadRules approach it wont work, because the rule bellow will be override by the generic allow read in the first rule statement
    match /calculations/{id} {
      allow read: if belongsTo(resource.data.user_uid);
    }
    
    function belongsTo(userId) {
        return request.auth.uid == userId;
    }
    

    【讨论】:

      猜你喜欢
      • 2018-04-05
      • 1970-01-01
      • 2019-09-15
      • 1970-01-01
      • 2019-05-26
      • 2018-04-04
      • 1970-01-01
      • 1970-01-01
      • 2021-11-22
      相关资源
      最近更新 更多