文档字段的 Firestore 规则
Posted
技术标签:
【中文标题】文档字段的 Firestore 规则【英文标题】:Firestore rules for document field 【发布时间】:2018-09-29 20:56:17 【问题描述】:我在 Firestore 中为文档设置安全规则而苦苦挣扎。使用 RTDB 可以为特定对象属性设置规则,我正在尝试对 Firestore 做同样的事情。
RTDB 代码:
"users":
".read": true,
".indexOn": ["profile/name"],
"$uid":
".read": "auth != null",
".write":
"$uid === auth.uid && !data.exists()",
"profile":
"birthday":
".write": "$uid === auth.uid"
,
"name":
".write": "$uid === auth.uid"
,
"banned":
".write": "root.child('admins').child(auth.uid).exists()"
在 Firestore 中的相同代码下方:
service cloud.firestore
match /databases/database/documents
match /users/
allow read
match /$user
allow read: if request.auth.uid != null
allow write: if request.auth.uid == request.resource.id && exists(/databases/$(database)/documents/users/$(request.resource.id)) === false
match /birthday
allow write: if request.auth.uid == request.resource.id
match /name
allow write: if request.auth.uid == request.resource.id
match /banned
allow write: get(/databases/$(database)/documents/users/$(request.auth.uid)).data.userType > 3
当我为子集合编写安全规则时,它工作正常。但是对于文档字段,它不起作用。这是不可能的还是匹配参考中有一个特殊的path
段? The documentation 对此没有任何说明。
【问题讨论】:
【参考方案1】:您可以通过检查request.resource.data
属性来做到这一点。如documentation的这一部分所示。您只需要匹配文档级别。您使用if
条件检查字段规则。
但是,您无法控制对单个字段的读取权限。用户可以阅读或不阅读整个文档。如果您需要存储私有数据,请考虑将其添加到用户文档的子集合中。
这是一个例子
service cloud.firestore
match /databases/database/documents
// Make sure all cities have a positive population and
// the name is not changed
match /cities/city
allow update: if request.resource.data.population > 0
&& request.resource.data.name == resource.data.name;
【讨论】:
这可能适用于写入,但不适用于读取。它还创建了更多的意大利面条代码。 对于读取,您只需省略request.
我发给您的文档链接中显示了一个示例
我正在尝试了解您对 banned
字段的操作。您能否用所需的结果更新您的问题并发表评论,以便我看一下?
使用 Cloud Firestore,您无法限制单个字段的读取。您只能允许/阻止阅读文档。但是,可以控制单个字段的写入。如果您希望存储私有数据,您应该向用户文档添加一个集合,该集合可以包含此私有数据。我通常有 3 个集合,public
、private
(用户可以访问)和internal
。你也可以添加一个admin
集合。
也许这会有所帮助:您可以使用writeFields
property 访问传入写入的目标字段。所以你可以这样做:allow write: if isAdministrator() || !('banned' in request.writeFields);
【参考方案2】:
Looks like this is now supported:
service cloud.firestore
match /databases/database/documents
// Allow the user to read data if the document has the 'visibility'
// field set to 'public'
match /cities/city
allow read: if resource.data.visibility == 'public';
resource
变量引用请求的文档,resource.data
是存储在文档中的所有字段和值的映射。
举一个具体的例子,在我的例子中,只有当请求用户在 groups 的 members 字段(这是一个数组)中时,我才需要提供对组的读取访问权限 集合。所以我这样做了:
rules_version = '2';
service cloud.firestore
match /databases/database/documents
function isMember(userId)
return (userId in resource.data.members);
match /groups/group
allow read: if request.auth != null && isMember(request.auth.uid);
//...
【讨论】:
以上是关于文档字段的 Firestore 规则的主要内容,如果未能解决你的问题,请参考以下文章
即使firestore安全规则中的文档字段不可用,也如何允许访问?
有没有办法使用Firestore安全规则使用FieldValue.increment()更新文档字段?
Firestore 安全规则 - 如何检查某个字段是不是被修改?
如何从Swift中的Cloud FireStore Firebase访问特定字段