1

我正在使用 Firebase 实时数据库(使用 Angular 9),并且我需要设置一些规则来仅当用户拥有密码时才能访问这些数据。此外,如果他有密码,他可以更改它。

这是我的数据库:

sessions
  session_one
    some_data: 'can',
    some_data_2: 'you',
    old_pin: 1234,
    pin: 1234
  session_two
    some_data: 'help',
    some_data_2: 'me',
    old_pin: -1,
    pin: -1
  session_three
    some_data: 'please?',
    some_data_2: 'thanks',
    old_pin: 5555,
    pin: 5555

还有我的规则:

 {
   "rules": {
     "sessions": {
       "$session": {
         ".indexOn": "pin",
         ".read": "query.orderByChild === 'pin' &&
                   query.equalTo === data.child('pin').val()",
         ".validate": "!data.exists() ||
                   newData.child('old_pin').val() === data.child('pin').val()"

       }
     }
   }
 }

我做了一些研究,发现在 Firebase 实时数据库中您无法读取元素的一部分,这里的问题是我想知道具有该键的元素是否存在让我只有在我有 pin 码时才能读取。

例如,我搜索名为“session_three”的会话(如果存在)并且我有我可以读取和修改数据的密码,如果存在并且我没有我无法读/写但我可以知道的密码如果存在,因为如果它不存在,我可以使用该名称创建一个新会话。

角代码:

this.db.database.ref("sessions/"+this.session).orderByChild('pin').equalTo(this.pin).once('value').then((snap) => {
  this.enterInSession(snap);
}).catch(() => {
  this.db.database.ref('sessions/' + this.inputSession).set({
      some_data: 'loren',
      some_data_2: 'ipsum',
      old_pin: -1
      pin: -1
    }).then(() => {
      this.enterInSession(this.inputSession);
    }).catch(() => {
      this.enterPinDialog();
    });
});

它工作得很好,问题是在'snap'中,当我输入正确的会话名称和pin时,响应是'null'而不是会话数据。

太感谢了!=)

4

1 回答 1

0

您需要在查询运行的级别上定义规则。由于您的查询在 上运行/sessions,这也是您需要定义.read规则的地方。这也立即说明了为什么这种方法不起作用:on/sessionsdata引用所有会话的数据,并且没有pin属性可以检查其值。

我发现最容易记住 Firebase 会在您附加侦听器时强制执行其安全规则,并且如果不阅读每个单独的文档,它就没有合理的方法来使用您的规则执行此操作,这不会“扩展”。


传递给安全规则的客户端的唯一信息是:

  1. 活动用户的身份验证令牌
  2. 正在读取/写入的数据的路径。
  3. 如果读取的是查询,则从查询中获取信息。

无法将其他自定义信息传递到安全规则中,因此您必须确保该信息在上述之一中。

我对此的常见解决方案是将任何安全信息编码到节点的密钥中。

sessions
  session_one_1234
    some_data: 'can',
    some_data_2: 'you',
    old_pin: 1234,
    pin: 1234
  session_two_-1
    some_data: 'help',
    some_data_2: 'me',
    old_pin: -1,
    pin: -1
  session_three_5555
    some_data: 'please?',
    some_data_2: 'thanks',
    old_pin: 5555,
    pin: 5555

现在您需要知道原始密钥(例如session_one 文档的 PIN 才能构建其路径,这是阅读它所必需的。

与此相关的更简单的规则:

{
   "rules": {
     "sessions": {
       "$session": {
         ".read": true, // if you know the path, you can read it
       }
     }
   }
 }

只要您不授予用户读取所有内容的权限/sessions,他们就没有机会找到会话节点的密钥。

于 2020-05-05T13:28:31.653 回答