为Firestore编写规则似乎自定义变量不起作用。有谁知道为什么或看到过类似的行为?使用下面我得到访问被拒绝,虽然uid在admin的数组中。
service cloud.firestore {
match /databases/{database}/documents {
match /conferences/{confid} {
allow read,write: if request.auth.uid in get(/databases/$(database)/documents/conferences/$(confid)).data.admin;
}
}
}
模拟器给出以下错误:
使用不存在资源的路径调用函数[get]:/ databases /%28default%29 / documents / meetings /%7Bconfid%7D
同样在真实设备上测试这个我被拒绝访问。
但是,如果我使用下面的文档ID,它就可以工作并获得访问权限。
service cloud.firestore {
match /databases/{database}/documents {
match /conferences/{confid} {
allow read,write: if request.auth.uid in get(/databases/$(database)/documents/conferences/ySWLb8NSTj9sur6n2CbS).data.admin;
}
}
}
显然我无法对每个ID进行硬编码。
UPDATE
除了用支持记录案例外,我还做了一些进一步的测试。在下面,模拟器现在授予访问权限。
service cloud.firestore {
match /databases/{database}/documents {
match /conferences/{confID}{
allow read, write: if request.auth.uid in get(/databases/$(database)/documents/conferences/$(confID)/permissions/permission).data.users;
}
}
}
作为参考,我使用以下来从我的网络应用程序查询:
db.collection("conferences")
.get()
.then(query => {
console.log("SUCCESS!!!")
query.forEach(function(doc) {
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
});
}).catch((e) => {
console.log(e)
})
这是来自浏览器的日志:
FirebaseError:权限丢失或不足。在JsonProtoSerializer.fromRpcStatus的新FirestoreError(webpack-internal:///./node_modules/@firebase/firestore/dist/index.cjs.js:352:28)(webpack-internal:///./node_modules/@firebase /firestore/dist/index.cjs.js:5649:16)在PersistentListenStream的JsonProtoSerializer.fromWatchChange(webpack-internal:///./node_modules/@firebase/firestore/dist/index.cjs.js:6146:44) eval上的.onMessage(webpack-internal:///./node_modules/@firebase/firestore/dist/index.cjs.js:14350:43)(webpack-internal:///./node_modules/@firebase/firestore/ dist / index.cjs.js:14279:30)在eval(webpack-internal:///./node_modules/@firebase/firestore/dist/index.cjs.js:14319:28)eval(webpack-internal: ///./node_modules/@firebase/firestore/dist/index.cjs.js:7411:20)
我使用的是最新的Firebase软件包5.8.3。
如果我将上述规则更改为类似于下面的简单内容,只要我与用户一起登录就可以访问:
service cloud.firestore {
match /databases/{database}/documents {
match /conferences/{confID}{
allow read, write: if request.auth.uid != null
}
}
}
这甚至让我更加困惑。这是因为规则更复杂,需要花费太长时间才能验证并拒绝访问权限吗?
更新2
通过Flutter在移动应用程序中快速测试。结果相同。此规则集拒绝访问。
service cloud.firestore {
match /databases/{database}/documents {
match /conferences/{confID}{
allow read, write: if request.auth.uid in get(/databases/$(database)/documents/conferences/$(confID)/permissions/permission).data.users;
}
}
}
我认为我的问题是查询与安全规则不匹配。如果您只访问单个特定文档,它将起作用,但如果您查询集合中的多个文档,则会被安全规则阻止。我有两个选择。重构我的数据,以便单个文档将保存我需要的所有数据或重新设计安全规则以匹配查询。最后,我在每个文档中附加了一个像UID这样的标识符,以确保查询符合安全规则。
一种解决方案是将具有权限的用户放入会议文档中的数组中,所以request.resource.data.permissions
所以,而不是这个:
get(/databases/$(database)/documents/conferences/$(confID)/permissions/permission).data.users
用这个:
request.resource.data.permissions
这不会解决get()
问题,但它将消除get()
呼叫的需要,这可以为您的配额节省15%或更多。