以下是我的 Firestore 规则。我有一个“用户”集合,其中文档 ID 是身份验证中用户的 UID。我只希望管理员访问某些用户数据或用户本身。
service cloud.firestore {
match /databases/{database}/documents {
match /{users=**} {
allow read: if isOwner() || isAdmin();
allow write: if isOwner();
}
function isOwner() {
return request.auth != null && request.auth.uid == resource.id;
}
function isAdmin() {
return request.auth != null && request.auth.token.user_type == 3;
}
}
}
这是我用来获取数据的函数:
const fetchUserDetails = async (userId: string) => {
const userDocRef = doc(FIREBASE_DB, 'users', userId);
console.log('Fetching userid: ', userId);
const userDocSnapshot = await getDoc(userDocRef);
if (userDocSnapshot.exists()) {
const userData = userDocSnapshot.data();
const addressesCollectionRef = collection(
FIREBASE_DB,
'users',
userId,
'addresses',
);
const addressesSnapshot = await getDocs(addressesCollectionRef);
const addresses = addressesSnapshot.docs.map(addressDoc =>
addressDoc.data(),
);
return {
...userData,
addresses,
};
}
// Handle the case where the user does not exist in Firestore
console.error('User not found in Firestore');
return null;
};
当我在 Firestore 中尝试模拟时,一切正常。管理员可以获取所有用户的信息,普通用户只能获取自己的信息。但是,当我尝试在 React Native 应用程序中使用上述代码获取用户数据时,我收到此错误:FirebaseError:缺少或权限不足。对于管理员来说它工作得很好,它可以获取自己的数据。但普通用户无法获取自己的数据。我检查到普通用户只尝试访问自己的数据而不是其他数据。
另外,如果我尝试将我的安全规则更改为此。现在连管理员都无法获取数据了。
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read: if isOwner(userId) || isAdmin();
allow write: if isOwner(userId);
}
function isOwner(userId) {
return request.auth != null && request.auth.uid == userId;
}
function isAdmin() {
return request.auth != null && request.auth.token.user_type == 3;
}
}
}
如果您希望
isOwner()
在使用以下代码行读取数据时工作:
const userDocRef = doc(FIREBASE_DB, 'users', userId);
const userDocSnapshot = await getDoc(userDocRef);
那么你必须将规则更改为:
service cloud.firestore {
match /databases/{database}/documents {
// 👇
match /users/{uid} {
allow read: if isOwner() || isAdmin();
allow write: if isOwner();
}
function isOwner(uid) {
return request.auth != null && request.auth.uid == uid;
}
function isAdmin() {
return request.auth != null && request.auth.token.user_type == 3;
}
}
}
通过这种方式,您将确保您的用户只能读取和写入他们的自己的数据。
请注意,您可以将安全规则级联到嵌套子集合。因此,如果您希望能够读取
addresses
子集合下的数据,那么您必须在文档 ID 的 match 子句中指定递归通配符 (=**)
。由于您对 users
集合执行此操作,因此您当前的访问规则不会级联。所以你必须使用类似的东西:
service cloud.firestore {
match /databases/{database}/documents {
// 👇
match /users/{uid=**} {
allow read: if isOwner(uid) || isAdmin(uid);
allow write: if isOwner(uid);
}
function isOwner(uid) {
return request.auth != null && request.auth.uid == uid;
}
function isAdmin() {
return request.auth != null && request.auth.token.user_type == 3;
}
}
}