Catch up on everything we announced at this year's Firebase Summit. Learn more

Структурирование правил безопасности Cloud Firestore

Правила безопасности Cloud Firestore позволяют контролировать доступ к документам и коллекциям в вашей базе данных. Гибкий синтаксис правил позволяет создавать правила, которые соответствуют чему угодно, от всех операций записи во всю базу данных до операций с конкретным документом.

В этом руководстве описывается основной синтаксис и структура правил безопасности. Объедините этот синтаксис с правилами безопасности условиями для создания законченного набора правил.

Объявление сервиса и базы данных

Правила безопасности Cloud Firestore всегда начинаются со следующего объявления:

service cloud.firestore {
  match /databases/{database}/documents {
    // ...
  }
}

service cloud.firestore декларация прицелы правила в облаке Firestore, предотвращение конфликтов между Cloud Firestore правилами и правилами безопасности для других продуктов , таких как Cloud Storage.

В match /databases/{database}/documents декларация определяет , что правила должны соответствовать любой базе данных Cloud Firestore в проекте. В настоящее время каждый проект имеет только одну базу данных с именем (default) по (default) .

Основные правила чтения / записи

Основные правила состоят из match заявления , указывающего путь к документу и allow выражение подробно при чтении указанных данных допускаются:

service cloud.firestore {
  match /databases/{database}/documents {

    // Match any document in the 'cities' collection
    match /cities/{city} {
      allow read: if <condition>;
      allow write: if <condition>;
    }
  }
}

Все операторы соответствия должны указывать на документы, а не на коллекции. Заявление матча может указывать на конкретный документ, как и в match /cities/SF или использовать маски , чтобы указать на какой - либо документ по указанному пути, как и в match /cities/{city} .

В приведенном выше примере оператор матча использует {city} подстановочные синтаксис. Это означает , что правило применяется к любому документу в cities коллекции, такие как /cities/SF или /cities/NYC - /cities/NYC . Когда allow выражения в операторе матча оцениваются, то city переменный будет решать имя документа города, такие как SF или NYC - NYC .

Гранулярные операции

В некоторых ситуациях, это полезно , чтобы сломать read и write в более детализированные операции. Например, вашему приложению может потребоваться применить другие условия при создании документа, чем при удалении документа. Или вы можете разрешить чтение одного документа, но запретить большие запросы.

read правило может быть разбито на get и list , в то время как write правило может быть разбито на create , update и delete :

service cloud.firestore {
  match /databases/{database}/documents {
    // A read rule can be divided into get and list rules
    match /cities/{city} {
      // Applies to single document read requests
      allow get: if <condition>;

      // Applies to queries and collection read requests
      allow list: if <condition>;
    }

    // A write rule can be divided into create, update, and delete rules
    match /cities/{city} {
      // Applies to writes to nonexistent documents
      allow create: if <condition>;

      // Applies to writes to existing documents
      allow update: if <condition>;

      // Applies to delete operations
      allow delete: if <condition>;
    }
  }
}

Иерархические данные

Данные в Cloud Firestore организованы в коллекции документов, и каждый документ может расширять иерархию за счет вложенных коллекций. Важно понимать, как правила безопасности взаимодействуют с иерархическими данными.

Рассмотрим ситуацию , когда каждый документ в cities коллекции содержит landmarks подколлекцию. Правила безопасности применяются только при согласованном пути, поэтому контроль доступа , определенный на cities коллекции не применяется к landmarks подколлекции. Вместо этого напишите явные правила для управления доступом к вложенным коллекциям:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      allow read, write: if <condition>;

        // Explicitly define rules for the 'landmarks' subcollection
        match /landmarks/{landmark} {
          allow read, write: if <condition>;
        }
    }
  }
}

Когда вложенности match заявления, путь внутреннего match заявления всегда относительно пути внешнего match заявления. Следовательно, следующие наборы правил эквивалентны:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      match /landmarks/{landmark} {
        allow read, write: if <condition>;
      }
    }
  }
}
service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city}/landmarks/{landmark} {
      allow read, write: if <condition>;
    }
  }
}

Рекурсивные подстановочные знаки

Если вы хотите , правила применяются к произвольно глубокой иерархии, используйте рекурсивный подстановочный синтаксис {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 и значение document переменного будет SF/landmarks/coit_tower .

Однако обратите внимание, что поведение рекурсивных подстановочных знаков зависит от версии правил.

Версия 1

По умолчанию правила безопасности используют версию 1. В версии 1 рекурсивные символы подстановки соответствуют одному или нескольким элементам пути. Они не совпадают пустой путь, так что match /cities/{city}/{document=**} совпадает с документами в подколлекциях , но не в cities коллекции, в то время как match /cities/{document=**} соответствует оба документам в cities сбор и подколлекция.

Рекурсивные символы подстановки должны стоять в конце оператора соответствия.

Версия 2

В версии 2 правил безопасности рекурсивные символы подстановки соответствуют нулю или более элементам пути. match/cities/{city}/{document=**} совпадает с документами в любых подколлекциях, а также документах в cities коллекции.

Вы должны выбрать в версии 2, добавив rules_version = '2'; в верхней части ваших правил безопасности:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the cities collection as well as any document
    // in a subcollection.
    match /cities/{city}/{document=**} {
      allow read, write: if <condition>;
    }
  }
}

У вас может быть не более одного рекурсивного подстановочного знака для каждого оператора сопоставления, но в версии 2 вы можете разместить этот подстановочный знак в любом месте оператора сопоставления. Например:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the songs collection group
    match /{path=**}/songs/{song} {
      allow read, write: if <condition>;
    }
  }
}

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

Перекрывающиеся заявления о совпадении

Это возможно для документа , чтобы соответствовать более одного match заявления. В случае , когда несколько allow выражения сопоставляются запрос, доступ разрешен , если какое - либо из условий является true :

service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the 'cities' collection.
    match /cities/{city} {
      allow read, write: if false;
    }

    // Matches any document in the 'cities' collection or subcollections.
    match /cities/{document=**} {
      allow read, write: if true;
    }
  }
}

В приведенном выше примере, все операции чтения и записи до cities коллекции будет разрешено , потому что второе правило всегда true , даже если первое правило всегда false .

Ограничения правил безопасности

При работе с правилами безопасности обратите внимание на следующие ограничения:

Предел Подробности
Максимальное число exists() , get() , и getAfter() вызывает по запросу
  • 10 для однодокументных запросов и запросов-запросов.
  • 20 для чтения нескольких документов, транзакций и пакетной записи. Предыдущее ограничение в 10 также применяется к каждой операции.

    Например, представьте, что вы создаете пакетный запрос на запись с 3 операциями записи и что ваши правила безопасности используют 2 вызова доступа к документам для проверки каждой записи. В этом случае для каждой записи используются 2 из 10 вызовов доступа, а для запроса пакетной записи используются 6 из 20 вызовов доступа.

Превышение любого предела приводит к ошибке отказа в разрешении.

Некоторые вызовы доступа к документам могут кэшироваться, и кэшированные вызовы не учитываются при подсчете ограничений.

Максимальная вложенная match глубина заявления 10
Максимальная длина пути, в сегментах пути, допускается в пределах набора вложенных match заявлений 100
Максимальное количество переменного захвата пути допускается в пределах набора вложенных match заявлений 20
Максимальная глубина вызова функции 20
Максимальное количество аргументов функции 7
Максимальное количество let привязок переменных в функцию 10
Максимальное количество рекурсивных или циклических вызовов функций 0 (не разрешено)
Максимальное количество выражений, оцениваемых за запрос 1,000
Максимальный размер набора правил Наборы правил должны соответствовать двум ограничениям по размеру:
  • предел 256 КБ на размер набора правил исходного текста опубликованного из Firebase консоли или из командной строки с помощью firebase deploy .
  • ограничение в 250 КБ на размер скомпилированного набора правил, которое возникает, когда Firebase обрабатывает источник и делает его активным на сервере.

Следующие шаги