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

Cloud Firestore Security Rules allow you to control access to documents and collections in your database. The flexible rules syntax allows you to create rules that match anything, from all writes to the entire database to operations on a specific document.

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

Service and database declaration

Cloud Firestore Security Rules всегда начинаются со следующего заявления:

service cloud.firestore {
  // The {database} wildcard allows the rules to reference any database,
  // but these rules are only active on databases where they are explicitly deployed.
  match /databases/{database}/documents {
    // ...
  }
}

Объявление service cloud.firestore ограничивает действие правил только Cloud Firestore , предотвращая конфликты между Cloud Firestore Security Rules и правилами для других продуктов, таких как Cloud Storage.

The match /databases/{database}/documents declaration specifies that rules should match any Cloud Firestore database in the project. While a project can contain up to 100 databases, only the first database created is designated as the default.

Cloud Firestore Security Rules are applied separately for each named database in your project. This means that if you create multiple databases, you must manage and deploy rules for each one individually. For detailed instructions on deploying your updates, see Deploy your updates .

Basic read/write rules

Основные правила включают в себя оператор 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>;
    }
  }
}

All match statements should point to documents, not collections. A match statement can point to a specific document, as in match /cities/SF or use wildcards to point to any document in the specified path, as in match /cities/{city} .

In the example above, the match statement uses the {city} wildcard syntax. This means the rule applies to any document in the cities collection, such as /cities/SF or /cities/NYC . When the allow expressions in the match statement are evaluated, the city variable will resolve to the city document name, such as SF or NYC .

Granular operations

In some situations, it's useful to break down read and write into more granular operations. For example, your app may want to enforce different conditions on document creation than on document deletion. Or you may want to allow single document reads but deny large queries.

Правило 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>;
    }
  }
}

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

Data in Cloud Firestore is organized into collections of documents, and each document may extend the hierarchy through subcollections. It is important to understand how security rules interact with hierarchical data.

Consider the situation where each document in the cities collection contains a landmarks subcollection. Security rules apply only at the matched path, so the access controls defined on the cities collection do not apply to the landmarks subcollection. Instead, write explicit rules to control access to subcollections:

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>;
    }
  }
}

Recursive wildcards

Если вы хотите, чтобы правила применялись к произвольно глубокой иерархии, используйте рекурсивный синтаксис с подстановочными знаками {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>;
    }
  }
}

When using the recursive wildcard syntax, the wildcard variable will contain the entire matching path segment, even if the document is located in a deeply nested subcollection. For example, the rules listed above would match a document located at /cities/SF/landmarks/coit_tower , and the value of the document variable would be SF/landmarks/coit_tower .

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

Версия 1

Security rules use version 1 by default. In version 1, recursive wildcards match one or more path items. They do not match an empty path, so match /cities/{city}/{document=**} matches documents in subcollections but not in the cities collection, whereas match /cities/{document=**} matches both documents in the cities collection and subcollections.

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

Версия 2

In version 2 of the security rules, recursive wildcards match zero or more path items. match/cities/{city}/{document=**} matches documents in any subcollections as well as documents in the cities collection.

Для активации версии 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>;
   }
 }
}

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

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; см. раздел «Защита запросов к группам коллекций» .

Overlapping match statements

Документ может соответствовать более чем одному условию 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 .

Security rule limits

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

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

    For example, imagine you create a batched write request with 3 write operations and that your security rules use 2 document access calls to validate each write. In this case, each write uses 2 of its 10 access calls and the batched write request uses 6 of its 20 access calls.

Превышение любого из этих пределов приведет к ошибке "Доступ запрещен".

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

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

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