【问题标题】:Firebase Database Rules: Unknown variable '$memberId1'Firebase 数据库规则:未知变量“$memberId1”
【发布时间】:2017-03-30 06:04:46
【问题描述】:

我有以下 Firebase 数据库:

我想添加数据库规则以保护只有适当的用户才能访问他们的消息。

当我添加以下内容时,出现错误:

谁能给点建议?

谢谢

更新

findMessages(chatItem: any): Observable<any[]> { // populates the firelist
    return this.af.database.list('/message/', {
        query: {
            orderByChild: 'negativtimestamp'
        }
    }).map(items => {
        const filtered = items.filter(
            item => ((item.memberId1 === chatItem.memberId1 && item.memberId2 === chatItem.memberId2)
                || (item.memberId1 === chatItem.memberId2 && item.memberId2 === chatItem.memberId1))
        );
        return filtered;
    });
}

【问题讨论】:

  • 嗯,系统不知道什么变量 memberId1/2,它只是一个通配符。您应该将此成员保存在用户列表/消息等中,然后参考它

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


【解决方案1】:

.read 规则的表达式中,以$ 开头的变量代表路径中的键。

但是,成员 ID 不是键;他们是数据成员。要在表达式中使用它们,您可以使用data 快照的childval 方法。像这样:

{
  "rules": {
    "message": {
      "$key": {
        ".read": "data.child('memberId1').val() === auth.uid || data.child('memberId2').val() === auth.uid"
      }
    }
  }
}

【讨论】:

  • 这会保存到 Firebase 规则中,但是当我运行我的应用程序时,会出现以下错误。我的用户已通过 Firebase 进行身份验证,并且确实具有正确的 uidEXCEPTION: Uncaught (in promise): Error: permission_denied at /message: Client doesn't have permission to access the desired data. Error: permission_denied at /message: Client doesn't have permission to access the desired data.
  • 您需要为chat 路径添加额外的规则。此答案仅与问题中提到的 message 路径有关;它不包含一套完整的规则。您需要将 chat 添加到规则 JSON - 使用适当的 .read 等。
  • 谢谢,是的,我添加了等效的chat 规则。我认为这个错误与我的auth 有关,因为如果我有以下规则,那么我会间歇性地收到错误:auth != null
  • 请注意,您无法使用规则读取messages 的列表。您只能阅读经过身份验证的用户所属的个别消息。这通常被称为不能将规则用作过滤器,并且是预期的行为。见stackoverflow.com/a/14298525/6680611
  • 是的,这就是我想要的行为。如果我尝试访问其他人的消息,则会出现上述错误。过滤器正在应用程序本身的Observable 上完成。规则是阻止某人入侵该应用程序,并阻止访问其他人的消息。
【解决方案2】:

您应该有定义成员的变量,然后引用这些变量。

这是来自Firebase security docs的聊天示例。

{
  "rules": {
    "room_names": {
      // any logged in user can get a list of room names
      ".read": "auth !== null",
  "$room_id": {
    // this is just for documenting the structure of rooms, since
    // they are read-only and no write rule allows this to be set
    ".validate": "newData.isString()"
  }
},

"members": {
   // I can join or leave any room (otherwise it would be a boring demo)
   // I can have a different name in each room just for fun
   "$room_id": {
      // any member can read the list of member names
      ".read": "data.child(auth.uid).exists()",

      // room must already exist to add a member
      ".validate": "root.child('room_names/'+$room_id).exists()",

      "$user_id": {
         ".write": "auth.uid === $user_id",
         ".validate": "newData.isString() && newData.val().length > 0 && newData.val().length < 20"
      }
   }
},

"messages": {
  "$room_id": {
    // the list of messages for a room can be read by any member
    ".read": "root.child('members/'+$room_id+'/'+auth.uid).exists()",

    // room we want to write a message to must be valid
    ".validate": "root.child('room_names/'+$room_id).exists()",

    "$message_id": {
      // a new message can be created if it does not exist, but it
      // cannot be modified or deleted
      // any member of a room can write a new message
      ".write": "root.child('members/'+$room_id+'/'+auth.uid).exists() && !data.exists() && newData.exists()",

      // the room attribute must be a valid key in room_names/ (the room must exist)
      // the object to write must have a name, message, and timestamp
      ".validate": "newData.hasChildren(['user', 'message', 'timestamp'])",

      // the message must be written by logged in user
      "user": {
         ".validate": "newData.val() === auth.uid"
      },

      // the message must be longer than 0 chars and less than 50
      "message": { ".validate": "newData.isString() && newData.val().length > 0 && newData.val().length < 50" },

      // messages cannot be added in the past or the future
      // clients should use firebase.database.ServerValue.TIMESTAMP
      // to ensure accurate timestamps
      "timestamp": { ".validate": "newData.val() <= now" },

      // no other fields can be included in a message
      "$other": { ".validate": false }
    }
  }
}

} }

【讨论】:

    猜你喜欢
    • 2020-12-23
    • 1970-01-01
    • 2017-05-24
    • 2018-09-03
    • 2017-07-15
    • 1970-01-01
    • 2020-02-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多