Подтвердить что ты не робот

Правила безопасности Firebase: ограничивайте запись только этим uid, за исключением нескольких полей

В Firebase у меня есть users "node" , который выглядит так:

users: {
  someUid: {
    username: 'someUsername'
    activeConversations: {},
    profile_picture: ''
    ... lots of other children
  },
  ...
},
anotherNode: {

},
... hundreds of other nodes

Мои правила прямо сейчас:

{
  "rules": {
    ".read": true,
    ".write": true,
    "users": {
      ".indexOn": [
        "username"
      ]
    },
    "friendRequests": {
      ".indexOn": [
        "timeSent"
      ]
    }
  }
}

Что я хочу сделать, это ограничить доступ к дочерним элементам в users "node" только клиенту, которому принадлежит ребенок. Так, например, дочерний someUid должен записываться только клиентом с помощью uid someUid. Другой "node" как anotherNode может быть доступен для записи/чтения любым зарегистрированным клиентом. Кроме того, любой зарегистрированный клиент должен иметь возможность писать на profile_picture и activeConversations в документе users.

Как я могу достичь этого без необходимости устанавливать правило чтения/записи для каждого node?

Спасибо

4b9b3361

Ответ 1

Наличие ".read": true, ".write": true в корне вашей базы данных - это идея очень плохой. Буквально каждый мог просто стереть всю вашу базу данных или вставить любые данные в любое время. Это связано с тем, что .read и .write управляют каскадом, поэтому, если вы оцениваете значение true на некотором node, у человека есть разрешение для всех дочерних элементов этого node.

К счастью, более безопасные правила, такие как правила, которые вы предлагаете, просты в реализации. Я предполагаю, что someUid равен пользователям auth.uid, которые вы можете сделать:

{
  "rules": {
    "users": {
      ".indexOn": ["username"],
      // wildcard, matches any node under 'users'
      "$someUid": {
        ".read": "auth != null",
        ".write":"auth != null",
        "$other" : {
          ".validate": "($other == 'profile_picture' || $other == 'activeConversations') || auth.uid == $someUid" // only that own user can change their username
        }
      }
    }
  }
}

Я пропустил ваш friendRequests node, потому что я не уверен, какие правила безопасности вы хотите для этого, но я надеюсь, что этого достаточно, чтобы вы начали.

Firebase docs очень хорошо описывают этот материал.

Ответ 2

Я думаю, что @Bradley Mackey был почти там, но просто нуждался в небольшой настройке.

{
  "rules": {
    "users": {
      ".indexOn": ["username"],
      // wildcard, matches any node under 'users'
      "$someUid": {
        "$other" : {
          ".read": "($other == 'profile_picture' || $other == 'activeConversations') || auth.uid == $someUid", 
          ".write": "($other == 'profile_picture' || $other == 'activeConversations') || auth.uid == $someUid", 
        }
      }
    },
    "$anythingelse": {
      ".read": "auth != null",
      ".write": "auth != null",
    }
  }
}

Поле ".validate": гарантирует, что поле соответствует определенному формату. Чтение и запись здесь должны дать каждому доступ к чтению и записи, если поле является профилем profile_picture или activeConversations, и предоставить пользователю доступ ко всему остальному.

EDIT:

Я добавил в другое правило, которое позволит доступ на чтение и запись любому подписанному пользователю к любому из узлов, не являющихся пользователями.

Ответ 3

В соответствии с документацией firebase вы можете ограничить права доступа на уровне пользователя и уровне данных

Например,

    // These rules grant access to a node matching the authenticated
    // user ID from the Firebase auth token
    {
      "rules": {
        "users": {
          "$uid": {
            ".read": "$uid === auth.uid",
            ".write": "$uid === auth.uid"
          }
        }
      }
    }

Кроме того, вы можете ограничить разрешение записи на чтение на уровне данных,

{
  "rules": {
    "messages": {
      "$message": {
        // only messages from the last ten minutes can be read
        ".read": "data.child('timestamp').val() > (now - 600000)",

        // new messages must have a string content and a number timestamp
        ".validate": "newData.hasChildren(['content', 'timestamp']) && newData.child('content').isString() && newData.child('timestamp').isNumber()"
      }
    }
  }
}

Пройдите через официальную документацию по firebase, https://firebase.google.com/docs/database/security/quickstart https://firebase.google.com/docs/database/security/user-security https://firebase.google.com/docs/database/security/securing-data