英文:
Firebase Firestore Rules: Allow read/write only if auth.id == request.data.id
问题
这是您提供的一段代码和问题描述。以下是翻译的部分:
我正在使用以下规则:
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    
    // Documents can only be read or written by authenticated users
    match /{document=**} {
      allow read, write: if request.auth != null && request.auth.uid == resource.data.uid;
    }
  }
}
根据我的理解,这应该意味着:“只有在用户经过身份验证且其 uid 与他们正在读取或写入的文档的 uid 匹配时,才允许读取或写入操作”。
然而,我不断收到“permission-denied”错误。
这是我正在使用的代码(Dart/Flutter):
static FirebaseFirestore instance = FirebaseFirestore.instance;
static CollectionReference colRef = instance.collection('someCollection');
使用此包装方法(已更新):
Future<void> updateData() async {
    final uid_ = FirebaseAuth.instance.currentUser!.uid;
    final data = {'uid': uid_};
    await colRef.doc(uid_).set(data);
}
基本上,我将用户的 uid 传递给 updateData 函数,并确保文档具有相同的 uid,以符合规则。
我做错了什么?
编辑:
我尝试过的事情:
- 
确保用户已经通过身份验证,以及将正确的
uid传递给包装函数。 - 
使用
set方法而不是update方法,以避免如果文档尚不存在会出现任何问题。 - 
在了解有关
resource对象的更多信息后,将uid附加到data映射中。 - 
在
rules之间切换,从request.auth.uid == resource.data.uid到request.auth.uid == resource.id。 - 
将规则更改为仅为
request.auth != null,这最终按预期工作,但对于我的舒适区来说有点太宽泛。然而,这证明了用户已通过身份验证。我只需要一种方法来将auth.uid与数据映射对象内的document.id或uid进行比较。 - 
更改包装方法以明确使用
FirebaseAuth.instance。 
具体错误:
flutter: [cloud_firestore/permission-denied] The caller does not have permission to execute the specified operation.
英文:
I am using these rules:
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    
    // Documents can only be read or written by authenticated users
    match /{document=**} {
      allow read, write: if request.auth != null && request.auth.uid == resource.data.uid;
    }
  }
}
From my understanding, this should mean: "Allow read or write operations ONLY IF the user is authenticated and their uid matches the uid of the document they are reading or writing".
Yet, I continually get permission-denied errors.
This is the code I am using (Dart/Flutter):
  static FirebaseFirestore instance = FirebaseFirestore.instance;
  static CollectionReference colRef = instance.collection('someCollection');
With this wrapper method (updated):
Future<void> updateData() async {
    final uid_ = FirebaseAuth.instance.currentUser!.uid;
    final data = {'uid': uid_};
    await colRef.doc(uid_).set(data);
}
Basically, I am passing the user uid to the updateData function, and ensuring the document has the same uid so it conforms with the rules.
What am I doing wrong?
EDIT:
Things that I have tried:
- 
Ensured that the user was authenticated and that the correct
uidwas being passed to the wrapper function. - 
Used the
setmethod instead of theupdatemethod to avoid any issues if the document does not yet exist. - 
Appended the
uidto thedatamap after learning more about theresourceobject. - 
Toggled the rules between
request.auth.uid == resource.data.uidandrequest.auth.uid == resource.id. - 
Changed the rule to only be
request.auth != null, which ended up working as expected, but is a bit too broad for my comfort zone. Yet, this is proof that the user is authenticated. I just need a way to compare theauth.uidwith either thedocument.idoruidwithin the data map object. - 
Changed the wrapper method to explicitly use
FirebaseAuth.instance. 
The specific error:
flutter: [cloud_firestore/permission-denied] The caller does not have permission to execute the specified operation.
答案1
得分: 1
The key was that you're trying to write the uid field for the first time.
Your rules now do this:
resource.data.uid
The resource here refers to the document as it exists before the current operation, which doesn't seem to have the uid value yet.
If you want to refer to the document as it'll exist after the write operation (if that write operation is allowed), use:
request.resource.data.uid
Also see the documentation on the resource and request.resource variables.
英文:
The key was that you're trying to write the uid field for the first time.
Your rules now do this:
resource.data.uid
The resource here refers to the document as it exists before the current operation, which doesn't seem to have the uid value yet.
If you want to refer to the document as it'll exist after the write operation (if that write operation is allowed), use:
request.resource.data.uid
Also see the documentation on the resource and request.resource variables.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论