Правило базы данных "Поймай все остальное" в Firebase
Возможно, я слишком много занимаюсь этой проблемой с точки зрения SQL, но у меня возникают проблемы с пониманием того, как правильно ограничить, каким детям должно быть разрешено заполнять узел.
Скажи, что я хочу вести учет продуктов с произвольными названиями. Каждый продукт должен содержать price
, но больше ничего не разрешено.
Мой наивный подход был добавить .validate
правила для продуктов, требующих, чтобы newData содержал price
ребенок, явно предоставляющий доступ на запись к price
узел, а затем удаляя все доступ $other
узел (что-то вроде предложения по умолчанию в операторе switch):
{
"rules": {
"$product": {
".read": true,
".write": true,
".validate": "newData.hasChildren(['price'])",
"price": {
".write": true,
".validate": "newData.isNumber()"
},
"$other": {
".read.": false,
".write": false,
}
}
}
}
Это не работает. Добавление нового продукта с {"price": 1234, "foo": "bar"}
все еще будет принят Однако, если я добавлю (Я сделал это неправильно, как-то.)".validate": false
Правило для $other
вместо этого ничего не принимается (например, {"price": 1234}
не допускается).
Есть ли способ реализовать нечто подобное тому, что я пытаюсь сделать здесь? Если нет, как правильно ограничить структуру данных в Firebase? Должен ли я сделать это вообще? Что мешает пользователю заполнить мою базу данных мусором, если я этого не сделаю?
1 ответ
Вы попали в несколько общих ям безопасности Firebase здесь. Наиболее распространенным является то, что разрешение распространяется каскадно: как только вы предоставили разрешение на чтение или запись на определенном уровне дерева, вы не можете отобрать это разрешение на более низком уровне.
Это означает, что эти правила неэффективны (поскольку вы уже предоставили чтение / запись на один уровень выше):
"$other": {
".read.": false,
".write": false,
}
Чтобы решить проблему, вы должны понимать, что .validate
правила различны: данные считаются действительными только при соблюдении всех правил проверки. Таким образом, вы можете отклонить $other
данные с правилами валидации:
{
"rules": {
"$product": {
".read": true,
".write": true,
".validate": "newData.hasChildren(['price'])",
"price": {
".validate": "newData.isNumber()"
},
"$other": {
".validate": false
}
}
}
}