Firebase数据库规则允许按字段读取更深的节点

时间:2018-01-12 17:59:58

标签: firebase firebase-realtime-database firebase-security

我为每个具有privacy字段的用户提供了项目(请参阅下面的结构)。我需要使用规则,允许所有者用户阅读他的所有项目,但另一个用户只能阅读隐私项目> 0(0表示私人物品)。所以请帮我创建这个规则。

我当前的规则不起作用,因为它不允许在我的Android应用中使用getReference("items/{userUid}").addChildEventListener来阅读用户的项目。

root   
 items
  {userUid}
   {itemUid}
     name: a
     privacy: 0     
   {itemUid}
     name: b
     privacy: 1

规则:

"items": {
      "$uid": {
        "$itemUid": {
          ".read":  "$uid === auth.uid || data.child('privacy').val() > 0" 
        },
        ".write": "auth != null && $uid === auth.uid"
      }
    }

1 个答案:

答案 0 :(得分:1)

您说您尝试阅读items/{userUid},但您的规则设置为items/{userUid}/{itemUid}。您应该移除那个更深的孩子,并将您的阅读规则保持在{userUid}

"items": {
  "$uid": {
    ".read":  "$uid === auth.uid || data.child('privacy').val() > 0",
    ".write": "auth != null && $uid === auth.uid"
  }
}

更新1:请记住rules are not filters。这意味着用户可以从该节点读取所有数据,或者根本不读取任何数据。但是,使用recently introduced Query-based rules可以解决您的问题。

您可以将您正在使用的查询保留为阅读所有者数据

getReference("items/{userUid}").addChildEventListener

但是当为其他用户读取数据时,您需要对其进行过滤以仅显示privacy>0

getReference("items/{userUid}").orderByChild('privacy').startAt(1).addChildEventListener

orderByChild('privacy').startAt(1)相当于privacy>=1

然后,您可以将此查询添加到规则中,以确保仅在使用此查询时才读取此数据:

{
    "rules": {
    "items": {
        "$uid": {
            ".read":  "$uid == auth.uid || (query.orderByChild === 'privacy' && query.startAt === 1)",
            ".write": "auth != null && $uid === auth.uid",
            ".indexOn":["privacy"]
        }
    }
  }
}

请注意,在按隐私排序数据时,我还向improve performance添加了.indexOn

更新2:要直接访问项目,您可以使用以下规则:

".read": "(auth != null && $uid === auth.uid) || (auth != null && query.orderByKey) || (auth != null && query.orderByChild === 'privacy' && query.startAt === '1')"

并使用以下方式访问它:

getReference(ref_to_items_userUid).orderByKey().equalTo(itemKey)