【问题标题】:Firebase security rule for data in same child同一子项中数据的 Firebase 安全规则
【发布时间】:2019-11-15 22:17:28
【问题描述】:

我的数据库结构是。

Homeland
 +Ui4PSHU0kCPGpFJ6jWIJPOdLvEds
  +service
  +quta
  +period
+55dwaSHU0kCPGpFJ6jWIJPOdLvEds
  +service
  +quta
  +period

我想公开“服务”和“quta”孩子,但只有注册用户才能显示“句号”孩子。但是我的用户目录存在问题。

首先我想测试我的 $uid 是否可以。但我不能。当我删除到 $uid 时它可以工作,只使用“Homeland”。所以它没有工作

{
  "rules": {
    "Homeland": {
         "$uid" : {
           ".read": true,
    ".write": "auth !== null"
         },
        },
    ".read": "auth !== null",
    ".write": "auth !== null"
  }
}

这是工作

{
  "rules": {
    "Homeland": {
           ".read": true,
    ".write": "auth !== null"
        },
    ".read": "auth !== null",
    ".write": "auth !== null"
  }
}

更新

按照 samthecodingman 所述更改我的安全规则。

{
  "rules": {
    "Homeland": {
      "$uid" : {
        "service": {
          ".read": true, // <-- publically readable
          ".write": "auth.uid === $uid" // <-- writable only by owner
        },
        "quta": {
          ".read": true, // <-- publically readable
          ".write": "auth.uid === $uid" // <-- writable only by owner
        },
        "period": {
          ".read": "auth !== null", // <-- readable by any logged in user
          ".write": "auth.uid === $uid" // <-- writable only by owner
        }
      },
    },
    "$other": { // <-- everywhere else not named above
      ".read": "auth !== null", // <-- allows read if logged in
      ".write": "auth !== null" // <-- allows write if logged in
    }
  }
}

代码

var kullanici = firebase.database().ref().child("Homeland").child(uservaluefrominput).child("service");
kullanici.on('value' ,function(datasnapshot) {


     sifre = datasnapshot.val();

     console.log(sifre);



});

但是代码和模拟都被拒绝读取值。

抓住错误。注意:这次我声明了用户标识。

try {

kullanici = firebase.database().ref().child("Homeland").child("Ui4PSHU0kCPGpFJ6jWIJPOdLvEO2").child("service");
kullanici.on('value' ,function(datasnapshot) {


     sifre = datasnapshot.val();

     console.log(sifre);



});

} catch (someError) {
  console.log('got some error: ', someError);
}

【问题讨论】:

  • 请将触发问题的代码添加到您的问题中。没有代码规则是毫无意义的。
  • 在var kullanici = ...下面添加kullanici.on('value', (s)=&gt;console.log(s), (err) =&gt; console.error(err))行会出现什么错误?
  • 我不确定如何使用你的代码,我使用了 try-catch 方法,但是我在控制台上什么也没有,请在第一条消息上检查我的代码。
  • try and catch 不会像您期望的异步代码那样工作。我在上面的注释中包含的那行是一个调试功能。将其按原样插入kullanici = firebase.database().ref()... 下方的行,然后运行您的代码。它所做的只是从on('value', ...) 获取响应并将其转换为控制台中的记录消息。然后复制这里的任何错误
  • "kullanici.on('value', (s)=>console.log(s), (err) => console.error(err)) ,function(datasnapshot) { " 这一行给了我一个 SyntaxError: unexpected token: ')'

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


【解决方案1】:

需要注意的是database rules cascade。即使您拒绝$uid 以外的任何人访问/users/$uid,但允许任何人访问/users/,任何人都可以修改更深的位置/users/$uid。

在上面的规则中,即使您为/Homeland/$uid 配置了规则,您也允许任何登录用户对根数据库进行读/写访问。

{
  "rules": {
    "Homeland": {
      "$uid" : {
        ".read": true,
        ".write": "auth !== null"
      },
    },
    ".read": "auth !== null", // <-- allows read everywhere if logged in
    ".write": "auth !== null" // <-- allows write everywhere if logged in
  }
}

要解决此问题,您可以引入$others 键,以便登录用户可以读取/写入数据库中除/Homeland 之外的任何位置,除非另有允许。

{
  "rules": {
    "Homeland": {
      "$uid" : {
        ".read": true,
        ".write": "auth !== null"
      },
    },
    "$other": { // <-- everywhere else not named above
      ".read": "auth !== null", // <-- allows read if logged in
      ".write": "auth !== null" // <-- allows write if logged in
    }
  }
}

下一步是在/Homeland/$uid 键下限制对/service、/quta 和/period 的访问。

{
  "rules": {
    "Homeland": {
      "$uid" : {
        "service": {
          ".read": true, // <-- publically readable
          ".write": "auth.uid === $uid" // <-- writable only by owner
        },
        "quta": {
          ".read": true, // <-- publically readable
          ".write": "auth.uid === $uid" // <-- writable only by owner
        },
        "period": {
          ".read": "auth !== null", // <-- readable by any logged in user
          ".write": "auth.uid === $uid" // <-- writable only by owner
        }
      },
    },
    "$other": { // <-- everywhere else not named above
      ".read": "auth !== null", // <-- allows read if logged in
      ".write": "auth !== null" // <-- allows write if logged in
    }
  }
}

但是,由于/Homeland 下的混合权限级别,您会受到可以对此数据执行的查询的限制。例如,您不能只使用查询列出/Homeland 下的所有用户,因为读取操作将被拒绝。

一个不起作用的查询是:

firebase.database().ref('/Homeland').on('child_added', (snap) => { ... })`

要以尽可能简单的方式解决此问题,您可以根据谁可以访问数据将/Homeland 拆分为/HomelandPublic 和/HomelandRegistered。其规则类似于:

{
  "rules": {
    "HomelandPublic": {
      "$uid" : {
        ".write": "auth.uid === $uid" // <-- writable only by owner
      },
      ".read": true // <-- publically readable
    },
    "HomelandRegistered": {
      "$uid" : {
        ".write": "auth.uid === $uid" // <-- writable only by owner
      },
      ".read": "auth !== null" // <-- readable by any logged in user
    },
    "$other": { // <-- everywhere else not named above
      ".read": "auth !== null", // <-- allows read if logged in
      ".write": "auth !== null" // <-- allows write if logged in
    }
  }
}

之前的查询现在将更改为:

// get publicly accessible data
firebase.database().ref('/HomelandPublic').on('child_added', (snap) => { ... }) // alternatively: once('value', (snap) => {})

// get data accessible by registered users
if (firebase.auth().currentUser) {
  firebase.database().ref('/HomelandRegistered').on('child_added', (snap) => { ... }) // alternatively: once('value', (snap) => {})
}

这应该会给你足够的知识来适应你的情况和需要。

【讨论】:

  • 我无法拆分或复制我的家乡目录。因为我的所有用户数据都在这个目录中。如果我将家乡目录拆分为 /register 和 /public,它的工作量会很大。但是,它是没用“$other”。更新了我的第一条消息我是如何使用的。
猜你喜欢
  • 1970-01-01
  • 2016-09-16
  • 1970-01-01
  • 2018-09-03
  • 2020-02-02
  • 1970-01-01
  • 2016-03-26
  • 2016-06-27
  • 1970-01-01
相关资源
最近更新 更多