配置Firestore安全规则以允许用户仅访问自己的数据 - 高效

时间:2017-10-07 07:41:09

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

将firestore与angularfire2 rc 2一起使用。

一切都在开发中非常好,没有有效的安全规则。

这些是无安全规则 - 客户端代码将在$COLLECTION_NAME/document下创建,更新和删除集合而不会出现问题。

service cloud.firestore {
    match /databases/{database}/documents {
        match /collectionA/{userId=**} { 
            allow read, write: if true;
        }
        match /collectionB/{userId=**}  {
            allow read, write: if true;
        }
        match /collectionC/{userId=**}  {
            allow read, write: if true;
        }
        match /collectionD/{userId=**}  {
            allow read, write: if true;
        }
    }
}

我想要的只是允许用户访问自己的数据。

我开始时遵循以下规则:

service cloud.firestore {
    match /databases/{database}/documents {
        match /collectionA/{userId=**} { 
            allow read, write: if request.auth.uid == userId;
        }
        match /collectionB/{userId=**}  {
            allow read, write: if request.auth.uid == userId;
        }
        match /collectionC/{userId=**}  {
            allow read, write: if request.auth.uid == userId;
        }
        match /collectionD/{userId=**}  {
            allow read, write: if request.auth.uid == userId;
        }
    }
}

但是,只要我添加任何类型的限制性规则,包括即使只是验证请求,也会被授权。

match /databases/{database}/documents {
    match /collectionA/{userId=**} { 
       allow read, write: if request.auth;
    }
    match /collectionB/{userId=**}  {
        allow read, write: if request.auth;
    }
    match /collectionC/{userId=**}  {
        allow read, write: if request.auth;
    }
    match /collectionD/{userId=**}  {
         allow read, write: if request.auth;
    }
}

我收到了代码权限错误。

  

[code = permission-denied]:权限丢失或不足。

     

FirebaseError:权限丢失或不足。

每个{userId}文档都包含一个集合,而该集合又包含文档,因此完整路径可能类似于

const entryCollection: AngularFirestoreCollection<Entry> = this.angularfirestore.collection('collectionC/' + user.uid + '/records' + '/2017-40' + '/entries');

请求应进行身份验证,因为访问权限仅在使用firebase身份验证进行身份验证后在客户端中授予。日志记录表明uid存在,实际上在collectionA或B或C或D下面创建文档时,user.uid文档是使用uid命名的。

4 个答案:

答案 0 :(得分:4)

就我而言,我需要创建用户的权限,所以其他解决方案对我不起作用。我还必须允许访问/ users / {userId}。这是我的代码:

service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow read, write: if request.auth.uid == userId;
      match /{allSubcollections=**} {
        allow read, write: if request.auth.uid == userId;
      }
    }
  }
}

答案 1 :(得分:3)

简短回答是{userId=**}导致userId成为path而不是string。这意味着将它与request.auth.uid(字符串)进行比较将失败。相反,你可能会想要这样的东西:

service cloud.firestore {
    match /databases/{database}/documents {
        match /collectionA/{userId}/{allSubcollections=**} { 
            allow read, write: if request.auth.uid == userId;
        }
    }
}

这样可以保证userId是一个字符串,然后匹配相应的子集(请注意,allSubcollections将是path)。

答案 2 :(得分:1)

我这样解决了这个问题。

service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
       match /{allSubcollections=**} {
        allow read, write: if request.auth.uid == userId;
      }
    }
  }
}

答案 3 :(得分:1)

以下设置对我有用(我使用allChildren而不是allSubcollection):

service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId}/{allChildren=**} {
      allow read, write: if request.auth.uid == userId;
    }
  }
}

allChildren将允许读/写用户文档的任何子集合。

有关此通配符匹配的详细信息为here