У меня возникла проблема: мои правила Firebase Firestore запрещают запросы аутентифицированных пользователей к базе данных. Я не очень хорошо разбираюсь в правилах Firestore, поэтому, вероятно, я что-то делаю неправильно со своей стороны.
Вот мои правила Firestore:
service cloud.firestore {
match /databases/{database}/documents {
match /{userID} {
allow read: if request.auth.uid == userID;
allow write: if request.auth.uid == userID
}
match /payment_options{
allow read: if request.auth != null;
allow write: if false
}
match /logs{
allow read, write: if false
}
}
}
Проверьте прикрепленное изображение на снимок моих данных Firestore, где красные линии представляют идентификаторы пользователей, полученные из аутентификации Firebase.
Я использую SDK Flutter Firestore и Firebase Auth, и я обязательно получаю/устанавливаю документы базы данных только ПОСЛЕ того, как пользователь вошел в приложение flutter, но я продолжаю получать следующее исключение:
Exception:
[cloud_firestore/permission-denied] The caller does not have permission to execute the specified
operation.
Вот мое дерево приложений, которое прослушивает изменения состояния аутентификации и направляет пользователя на страницу входа, если он не вошел в систему, и направляет его на главную страницу после входа в систему (операции Firestore происходят только ПОСЛЕ главной страницы):
class AppTreeWidgetState extends State<AppTreeWidget > {
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: Auth.currentUserStream,
builder: (context, snapshot){
if (snapshot.hasData) {
//TODO: Tell firebase to use the Signed in user to authenticate requests
//to the Firestore Database
return const MainPage();
} else {
return const LoginScreen();
}
}
);
}
}
Любая помощь или подсказки, как это запустить, будут очень признательны!
Я ожидал, что SDK Auth и Firestore будут взаимодействовать, и мои вызовы Firestore уже будут аутентифицированы, как только пользователь войдет в систему. Использование Firebase Auth SDK - я ошибаюсь? Нужно ли мне явно авторизовать вызовы к базе данных Firestore с использованием информации, полученной при входе пользователя в систему?





Я не уверен, как вы звоните и как ваши данные. но если вы уверены, что пользователь успешно аутентифицирован, то нет необходимости передавать дополнительную информацию в Firebase при вызове базы данных, поскольку статус аутентификации всегда автоматически прикрепляется к запросу.
я предлагаю попробовать {documents=**} — это подстановочный знак, который соответствует любому документу по указанному пути.
service cloud.firestore {
match /databases/{database}/documents {
match /{userID}/{documents=**} {
allow read: if request.auth.uid == userID;
allow write: if request.auth.uid == userID
}
match /payment_options/{documents=**} {
allow read: if request.auth != null;
allow write: if false
}
match /logs/{documents=**} {
allow read, write: if false
}
}
}
Пожалуйста, прежде чем внедрять, подумайте о следующем
Рекурсивные подстановочные знаки
Если вы хотите, чтобы правила применялись к произвольно глубокой иерархии, используйте рекурсивный синтаксис подстановочных знаков,
{name=**}. Например:service cloud.firestore { match /databases/{database}/documents { // Matches any document in the cities collection as well as any document // in a subcollection. match /cities/{document=**} { allow read, write: if <condition>; } } }При использовании рекурсивного синтаксиса подстановочных знаков переменная подстановочного знака будет содержать весь соответствующий сегмент пути, даже если документ находится в глубоко вложенной подколлекции.
Например, правила перечисленные выше, будут соответствовать документу, расположенному по адресу
/cities/SF/landmarks/coit_towerи стоимость документа переменная будетSF/landmarks/coit_tower.
поэтому используйте подстановочный знак только в том случае, если вы уверены в том, что коллекция может содержать/не содержать другую вложенную коллекцию, документы и всю ложь и должна соответствовать тому же уровню безопасности (условиям).
для более простого примера, если у вас есть str. лайк /allUsersData/{userId}/notPublic/{docId} и ты напишешь следующие правила
match /allUsersData/{documents=**} {
allow read: if request.auth != null;
allow write: if request.auth != null;
}
это означает, что вы даете пользователю авторизации разрешение не только читать документ (userId} в коллекции allUsersData, но также и все остальные коллекции и документы в этом дереве, то есть и коллекцию с именем notPublic.
поэтому при использовании wildcard имейте в виду, что правило будет применяться ко всему вложенному дереву данных.
поскольку я не вижу здесь точной реализации. если это не помогло, вам необходимо предоставить дополнительные сведения о реализации.
Правильный способ реализации доступа только для владельцев показан здесь: firebase.google.com/docs/rules/basics#content-owner_only_access. В настоящее время я бы вообще рекомендовал не использовать рекурсивные подстановочные знаки, поскольку они часто приводят к дырам в безопасности. Поэтому я бы просто использовал: match /some_collection/{userId}
Большое спасибо! В этом была проблема, ха-ха. Я предполагаю, что это означает, что я давал доступ к коллекции, а не к документам внутри коллекции?
@MikeScriven, пожалуйста, быстро прочтите отредактированную часть, так как она предоставит вам больше информации. это может быть полезно для вас.
спасибо @FrankvanPuffelen, я полностью согласен с тобой и добавил еще «нет» в свой ответ
Большое спасибо, ценю помощь. Я буду использовать рекурсивный подстановочный знак, поскольку это очень простое приложение, в котором есть только одно поле, которое необходимо сохранить для каждого пользователя (и, скорее всего, оно не изменится). Благодарю вас за информацию!
Ни один из ваших кодов на самом деле не обращается к базе данных, поэтому трудно сказать, что там не так. Пожалуйста, отредактируйте свой вопрос, чтобы показать минимальный код, который мы все можем запустить, чтобы воспроизвести проблему, и в этом коде позаботьтесь о том, чтобы доказать, что состояние приложения соответствует требованиям, установленным вашими собственными правилами безопасности (т. е. убедитесь, что пользователь в данный момент вошел в систему). ).