service cloud.firestore {
match /databases/{database}/documents {
match /pool/{poolId} {
allow read: if request.auth != null;
allow write: if request.auth != null && get(/databases/$(database)/documents/user/$(request.auth.uid)).data.admin == true;
}
}
}
Я написал предыдущие правила, следуя https://firebase.google.com/docs/firestore/security/rules-conditions#access_other_documents. Я ожидал, что для того, чтобы пользователь добавил новый документ в коллекцию pool, документ с идентификатором request.auth.uid должен существовать в коллекции user и иметь запись admin: true .
Но каждый запрос от Functions
pool.post('/add', async (req, res) => {
const added = await db.collection('pool').add({
...
});
});
Разрешено добавлять новый документ в коллекцию pool.
Даже следующие правила
service cloud.firestore {
match /databases/{database}/documents {
match /pool/{poolId} {
allow read, write: if false;
}
}
}
Не запрещать любые запросы от функций...
В чем проблема правил? Или в функциях есть что-то, из-за чего правила не работают? Или в моей конфигурации проекта...?
Что именно вы подразумеваете под «запросом от функций»? Где выполняется запрос? В облачной функции? Я предполагаю, что с помощью pool.post вы передаете приложение Express в свою облачную функцию HTTP.
@Mises, последняя показанная им конфигурация должна предотвращать запись, но функции все еще могут писать, так что есть проблема. Да, он мог проверить context.auth.admin === true в верхней части своей функции и отклонить запрос, но вопрос заключался в том, почему Firestore rules способ защиты Firestore от неавторизованных вызовов функций не работает. Я думаю, что ваша точка зрения верна, и что-то, что можно сделать в дополнение к тому, что он просит в качестве дополнительной меры безопасности. --- firebase.google.com/docs/firestore/security/…
@Mises Тогда правила работают для чего ...? Разве правила для запросов, поступающих в базу данных Firestore откуда угодно...?
@RenaudTarnec Я использую функции Firebase для добавления документа в базу данных Firestore.
Правила @ghchoi работают для звонков прямо в базу данных. Например, с помощью библиотеки Firebase JavaScript SDK. Браузер пользователя может обращаться к базе данных, если это разрешено правилами.
@Mises Что мне делать, если я хочу разрешить запросы только от определенных пользователей? Должен ли я использовать такое условие, как if (db.collection('user').get(request.auth.uid))...?
@ghchoi Для этого есть много возможностей. Один из способов похож на ваш вопрос. Но вы должны ограничить доступ к «пользовательской» коллекции, чтобы только «суперадмин» мог изменять там документы (Ну, не только, но это просто пример). Второй — проверить токен пользователя: request.auth.token.admin == true но вам нужно будет написать функцию firebase, чтобы назначить это поле токену пользователя.
Ваш вопрос очень распространен. Пожалуйста, прочитайте дубликаты, чтобы понять поведение. Суть в том, что вы не можете контролировать запросы, поступающие от бэкэндов, только от интерфейсов при использовании веб- и мобильных SDK.
Облачные функции для Firebase используют Node.js Admin SDK, который полностью обходит правила безопасности, поскольку считается «привилегированной средой».
Вы найдете примечание по этому аспекту в документе Firestore :
Примечание. Клиентские библиотеки сервера обходят все функции Cloud Firestore Security. Правила
Если вы хотите ограничить использование облачной функции HTTPS только пользователями Firebase вашего приложения (и определить, какой пользователь вызывает ее с помощью декодированного токена идентификатора), вы можете следовать следующему официальному образцу облачной функции Firebase: Авторизованная конечная точка HTTPS.
Что мне делать, если я хочу разрешить только запросы от определенных пользователей? Должен ли я использовать такое условие, как if (db.collection('user').get(request.auth.uid))...?
Я действительно не понимаю, где тогда использовать правила... Нельзя ли сделать так, чтобы мои Функции не обходили правила безопасности?
См. обновление для ограничения вашей облачной функции HTTPS только пользователями Firebase вашего приложения. Для «Я действительно не понимаю, где тогда использовать правила» => Правила применяются, когда клиентские SDK вызывают бессерверную серверную часть Firestore. Серверные SDK обходят их.
Не могли бы вы помочь мне еще немного? Я следовал авторизованной конечной точке HTTPS. Что я дополнительно хочу сделать, так это разрешить только некоторым авторизованным пользователям записывать в «пул» коллекции, в то время как все авторизованные пользователи могут читать коллекцию.
Так что я могу заменить const { initializeApp, applicationDefault } = require('firebase-admin/app'); на Client SDKs?
Нет, не используйте Clients SDK и продолжайте использовать Admin SDK. Как показано в строках с 61 по 63 в образце, токен Firebase ID, который был передан как токен носителя в заголовке авторизации, декодируется, и вы можете получить пользовательский идентификатор (req.user.uid). Вы должны написать логику в своей облачной функции, которая разрешает (или не разрешает) пользователю, идентифицированному его uid, выполнять определенное действие (чтение или запись).
Обратите внимание, что следующее предложение в моем последнем комментарии «разрешает (или не разрешает) пользователю, идентифицированному его uid, выполнять определенное действие» может сбивать с толку. На самом деле действие (чтение или запись из/в коллекцию pool) выполняется не пользователем, а облачной функцией. А в облачной функции вы получаете uid вызывающего абонента (см. комментарий выше) и решаете, можете ли вы писать или читать в/из коллекции на основе этого uid. другими словами, облачная функция действует как сервер приложений или промежуточное программное обеспечение.
Спасибо мастер. Я многому научился. Теперь я могу перенести много кода Function во Flutter. Я даже не знал, что Flutter может напрямую CRUD Firestore... Я думал, что мне нужен бэкенд для связи с Firestore DB. Теперь мне кажется яснее! Мой вопрос был закрыт, но еще раз спасибо.
Функции Firebase работают как «суперадминистратор». Вы можете буквально изменить правила в своей базе данных, если хотите использовать функции. Вам нужно написать свою собственную логику в функциях, чтобы защитить свои функции.