【问题标题】:Firebase security rules insufficient permissionsFirebase 安全规则权限不足
【发布时间】:2021-07-02 18:03:10
【问题描述】:

我在我的 firebase 项目中拥有所有者角色,我正在尝试保护我的 Firestore 数据库。我希望我的收藏在默认情况下受到保护,并且只有在我为其制定规则时才能访问。我在生产模式下创建了我的数据库。但是,出于某种原因,即使我指定了允许我访问集合的规则,我也会收到 Missing or insufficient permissions 错误

例如,当我注册用户时,我还想创建自己的用户集合。 注册用户有效,但创建我的收藏无效。

注册用户查询(工作并将用户添加到 Firebase 身份验证)

register(value) : Promise<any> {
    return new Promise<any>((resolve, reject) => {
        this.afAuth.createUserWithEmailAndPassword(value.email, value.password)
        .then(res => {
            resolve(res);
        }, err => {
            console.log(err)
            reject(err);
            })
    
    });
}

创建用户集合查询(CreateCurrentUserCollection 不起作用)

public async getCurrentUser() : Promise<any> 
    {
        return new Promise<any>((resolve, reject) => {
            let user = this.afAuth.onAuthStateChanged(function(user){
                if (user) {
                    resolve(user);
                } else {
                    reject('No user logged in');
                }
            });
        });
    }   

public CreateCurrentUserCollection(): void
{
  this.authService.getCurrentUser().then(res => {
        this.firestore.collection<User>("usersBackup")
            .add({
                uid: res.uid,
                username: res.email
            })
  });
}

Firebase 规则

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
      
       match /users {
        allow read, write: if
          request.time < timestamp.date(2221, 7, 20);
       }
       
       match /usersBackup {
        allow read, write: if
          request.time < timestamp.date(2221, 7, 20);
       }
  }
}

如果我添加以下规则,例如

match /{document=**} {
  allow read, write: if request.auth != null;

确实有效。但是,我的其他安全规则都不起作用,我想阻止某些用户访问某些文档。我错过了什么或做错了什么?如果您需要更多信息,请提前告诉我。谢谢。

更新

正如 Dharmaraj 在他的回答中指出的那样,安全规则必须指向文档而不是集合。这解决了我收藏的一个问题。但是,我也有一个项目集合,其中包含一个名为 projectMembers 的数组字段。我只希望在 projectMembers 数组中具有 uid 的用户能够访问项目文档。出于某种原因,它总是给我Missing or insufficient permissions 错误,即使项目集合是空的。

查询

    public getProjectsOfUser(userUid: string) : Observable<IProject[]> {
        return this.firestore.collection<IProject>("projects", ref => 
            ref.where("projectMembers", "array-contains", userUid))
           .valueChanges({ idField: 'id'});
}

Firebase 规则

    rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
      
       match /users/{userID} {
        allow read, write: if isSignedIn() && request.auth.uid == userID
       }
       
       match /usersBackup/{document=**} {
        allow read, write: if
          request.time < timestamp.date(2221, 7, 20);
       }
        
      match /projects/{projectId} {
        allow read, write: if 
            isProjectMember(projectId, request.auth.uid);
      }
      
      //functions
    function isSignedIn()
    {
        return request.auth != null;
    }
    
    function isProjectMember(projectId, userId) {
    return userId in get(/databases/$(database)/documents/projects/$(projectId)).data.projectMembers;
    }
    
  }
}

数据库结构

Firebase 游乐场

JWT 令牌通过 Angular 发送到 Firebase

【问题讨论】:

  • 将 /{userId} 或 /{DocId} 添加到这些以授予对特定文档的读/写权限。请查看我们的安全指南。 firebase.google.com/docs/rules
  • @Kato 我如何授予对集合的某些文档而不是其他文档的读取/读取权限?如果您可以看一下,我已经更新了我的问题
  • @Kato,您可以看到 jwt 通过角度发送的 user_id 与我的数据库中的 uid 匹配。不知何故,安全规则在 firebase 操场上起作用。为什么我的角度查询不起作用?
  • 您好,请尝试resource.data.projectMembers 是否像我在聊天中发布的那样工作。

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


【解决方案1】:

正如documentation中提到的,

所有匹配语句都应该指向文档,而不是集合。 match 语句可以指向特定文档,如 match /cities/SF 或使用通配符指向指定路径中的任何文档,如 match /cities/{city}。

如果您希望用户只编辑自己的文档,您应该尝试:

match /users/{userID} {
  allow read, write: request.auth != null && request.auth.uid == userID;
}

如果没有,那么您可以尝试添加recursive wildcard,以便将规则应用于该集合中的所有文档:

match /users/{document=**} {
  allow read, write: request.time < timestamp.date(2221, 7, 20);
}

请注意,如果您使用递归通配符,任何人都可以写入任何文档。

更新: 检查数组中是否存在 UID。

allow read, write: if request.auth != null && request.auth.uid in resource.data.projectMembers

【讨论】:

  • 尽可能使用第二个更具体的示例,并为每个子集合编写规则。几乎在所有情况下都避免使用通配符。正如 OP 所发现的,这通常会以意想不到的方式覆盖更具体的规则并造成安全漏洞。
  • 感谢@Kato 的评论。编辑了答案以强调这一点。
  • 谢谢 Dharmaraj,在这种情况下,将安全规则指向文档而不是集合有助于。但是,当我编写基于用户 UID 保护数据的安全规则时,我遇到了类似的问题。如果您可以看一下,我已经更新了我的问题
  • @Jiren 检查更新的答案。如果这对您不起作用,请分享您的数据库结构的屏幕截图以及您从规则中获得的任何错误。
  • @Dharmaraj 您的 isProjectMember 版本不起作用。它缺少 $(database) 变量作为参数,但即使我添加它,它也不起作用。除了权限不足错误之外,它本身的规则没有给我任何其他错误。我已经更新了我的问题,提供了我的数据库结构。如果可以,请看一下。
猜你喜欢
  • 2019-05-05
  • 2016-11-27
  • 1970-01-01
  • 2017-01-17
  • 1970-01-01
  • 2021-06-29
  • 1970-01-01
  • 1970-01-01
  • 2020-10-27
相关资源
最近更新 更多