为了账号安全,请及时绑定邮箱和手机立即绑定

Firebase 数据库规则 - 仅允许未经身份验证的用户过滤查询

Firebase 数据库规则 - 仅允许未经身份验证的用户过滤查询

慕莱坞森 2021-12-23 10:26:25
我有一个 Google Firestore 实时数据库,其中包含一个标志isPublic。如果设置为true,则details未经身份验证的用户可以读取子节点。如果设置为false,则该记录只能由一个(目前)经过身份验证和授权的用户访问。授权用户是唯一具有写权限的用户。此外,子节点private始终只向一个授权用户授予访问权限。我研究过的解决方案基于基于查询的规则 https://firebase.google.com/docs/database/security/securing-data#query-based_rules 不幸的是permission_denied,即使作为授权用户,我也收到了回复。除了信息:这是在使用 Firebase SDK 的 Vue JS 项目中。这是我的数据库示例。第一个产品应该details对未经身份验证的用户具有读取访问权限,但不能对private.第二个根本不应该显示给未经身份验证的用户,强制他们运行查询 dbRef.orderByChild('isPublic').equalTo(true)"products": {  "-pushIdxyz1" : {    "isPublic" : true,    "private" : {      "notes" : "lorem ipsum always private",      "soldDate" : ""    },    "details" : {      "imageURL" : "https://firebasestorage.imagexyz",      "keywords" : "this, that",      "title" : "Public product title",      "workCategory" : "hardware",    },  },  "-pushIdxyz2" : {    "isPublic" : false,    "private" : {      "notes" : "lorem ipsum always private",      "soldDate" : ""    },    "details" : {      "imageURL" : "https://firebasestorage.imagexyz",      "keywords" : "this, that",      "title" : "Secret product title",      "workCategory" : "hardware",    },  }}还有我不工作的规则"rules": {  "products": {    "$product_id": {      ".indexOn": "isPublic",      ".read": "query.equalTo == true || auth.uid == '[admin user id]'"      // alternative attempt      // ".read": "(query.orderByChild == 'isPublic' && query.equalTo == true) || auth.uid == '[admin user id]'",      ,      ".write": "auth.uid == '[admin user id]'",      "details": {        ".read": true,      },      "private": {        ".read": "auth.uid == '[admin user id]'",      }    }  }}对于未经授权的用户,此查询应授予对 details 子节点的读取访问权限:firebase.database().ref('products').orderByChild('isPublic').equalTo(true).once('value')  .then(...)此查询仅针对授权用户,应授予对所有数据的读取访问权限firebase.database().ref('products').once('value')  .then(...)使用当前设置,无论是否以授权用户身份登录,我都会收到任一查询的“权限被拒绝”。
查看完整描述

2 回答

?
米脂

TA贡献1836条经验 获得超3个赞

如果您希望用户能够从products节点读取数据,则需要.read在该节点上设置规则。并且由于您只想允许读取公共产品的查询,因此您应该验证该特定查询。


像这样的东西:


"rules": {

  "products": {

    ".indexOn": "isPublic",

    ".read": "(query.orderBy == 'isPublic' && query.equalTo == true)

              || auth.uid == '[admin user id]'"

  }

}

所以:


您定义的规则级别太低,这意味着所有读取/products都被拒绝。

你的规则不是检查orderBy字段。

请注意,.read您声明的附加规则在private这里毫无意义,因为无论如何,同一个用户已经获得了对整个 `products 节点的读取权限。


查看完整回答
反对 回复 2021-12-23
?
料青山看我应如是

TA贡献1772条经验 获得超8个赞

Franks 的回答为我指明了正确的方向(谢谢!),但我决定自己发布一个更完整的答案。


这是数据结构。请注意,我将“isPublic”更改为“isPublished”。“products”现在包含两个子节点:“private”和“public”。两者都使用相同的密钥。


// Firebase Data

"products": {

  "private" : {

    "-pushId_1" : {

      "notes" : "Private notes product 1",

      "soldDate" : ""

    },

    "-pushId_2" : {

      "notes" : "Private notes product 2",

      "soldDate" : ""

    }


  },

  "public" : {

    "-pushId_1" : {

      "imageURL" : "https://firebasestorage.imagexyz",

      "isPublished" : true,

      "title" : "Published product title",

    },

    "-pushId_2" : {

      "imageURL" : "https://firebasestorage.imagexyz",

      "isPublished" : false,

      "title" : "Unpublished product title, only accessible if authorized",

    }

  }

}

如果查询查找已发布的产品,规则允许管理所有内容并允许未经身份验证访问公共子节点


// Firebase Rules

{

  "rules": {

    "products" : {

      ".read": "auth.uid == '[admin user id]'",

      ".write": "auth.uid == '[admin user id]'",


      "public" : {

        ".indexOn": "isPublished",

        ".read": "(query.orderByChild == 'isPublished' && query.equalTo == true)"

      }

    }

  }

}

要创建新产品,我首先推送到“公开”,然后使用返回的密钥创建私有记录


// Add new product

db.ref('products/public').push(publicData)

  .then((data) => {

    key = data.key

    return key

  })

  .then((key) => {

    db.ref('products/private').child(key).update(privateData)

    return key

  })

  .then( ... )

要获得产品,公共/未经身份验证的用户必须isPublished在公共场所寻找。管理员可以循环访问公共和私有子节点


// Retrieve products - Public

db.ref('products/public').orderByChild('isPublished').equalTo(true).once('value')

  .then((data) => {

    let publicData = data.val()


    // Do something with the data

  })


// Retrieve products - Admin

db.ref('products').once('value')

  .then((data) => {

    let publicData = data.child('public').val()

    let privateData = data.child('private').val()


    // Do something with the data

  })


查看完整回答
反对 回复 2021-12-23
  • 2 回答
  • 0 关注
  • 120 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信