Правила Firestore с аутентификацией — Flutter

У меня возникла проблема: мои правила 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 с использованием информации, полученной при входе пользователя в систему?

Ни один из ваших кодов на самом деле не обращается к базе данных, поэтому трудно сказать, что там не так. Пожалуйста, отредактируйте свой вопрос, чтобы показать минимальный код, который мы все можем запустить, чтобы воспроизвести проблему, и в этом коде позаботьтесь о том, чтобы доказать, что состояние приложения соответствует требованиям, установленным вашими собственными правилами безопасности (т. е. убедитесь, что пользователь в данный момент вошел в систему). ).

Frank van Puffelen 07.05.2024 15:35
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
70
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я не уверен, как вы звоните и как ваши данные. но если вы уверены, что пользователь успешно аутентифицирован, то нет необходимости передавать дополнительную информацию в 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_acc‌​ess. В настоящее время я бы вообще рекомендовал не использовать рекурсивные подстановочные знаки, поскольку они часто приводят к дырам в безопасности. Поэтому я бы просто использовал: match /some_collection/{userId}

Frank van Puffelen 07.05.2024 15:36

Большое спасибо! В этом была проблема, ха-ха. Я предполагаю, что это означает, что я давал доступ к коллекции, а не к документам внутри коллекции?

Mike Scriven 07.05.2024 18:30

@MikeScriven, пожалуйста, быстро прочтите отредактированную часть, так как она предоставит вам больше информации. это может быть полезно для вас.

Rainy sidewalks 07.05.2024 19:28

спасибо @FrankvanPuffelen, я полностью согласен с тобой и добавил еще «нет» в свой ответ

Rainy sidewalks 07.05.2024 20:09

Большое спасибо, ценю помощь. Я буду использовать рекурсивный подстановочный знак, поскольку это очень простое приложение, в котором есть только одно поле, которое необходимо сохранить для каждого пользователя (и, скорее всего, оно не изменится). Благодарю вас за информацию!

Mike Scriven 10.05.2024 09:03

Другие вопросы по теме