Firebase Security Rules используют гибкие, мощные, настраиваемые языки, которые поддерживают широкий диапазон сложности и детализации. Вы можете сделать свои Rules настолько конкретными или настолько общими, насколько это целесообразно для вашего приложения. Правила Realtime Database используют синтаксис, похожий на JavaScript в структуре JSON. В правилах Cloud Firestore и Cloud Storage используется язык, основанный на языке общих выражений (CEL) , который основан на CEL с операторами match
allow
, поддерживающими условно предоставленный доступ.
Однако, поскольку это специальные языки, существует кривая обучения. Используйте это руководство, чтобы лучше понять язык Rules и глубже погрузиться в более сложные правила.
Выберите продукт, чтобы узнать больше о его правилах.
Базовая структура
Cloud Firestore
Firebase Security Rules в Cloud Firestore и Cloud Storage используют следующую структуру и синтаксис:
service <<name>> {
// Match the resource path.
match <<path>> {
// Allow the request if the following conditions are true.
allow <<methods>> : if <<condition>>
}
}
При разработке правил важно понимать следующие ключевые понятия:
- Запрос: метод или методы, вызываемые в операторе
allow
. Это методы, которые вы разрешаете запускать. Стандартные методы:get
,list
,create
,update
иdelete
. Удобные методыread
иwrite
обеспечивают широкий доступ для чтения и записи в указанной базе данных или пути хранения. - Путь: база данных или место хранения, представленное в виде пути URI.
- Правило: оператор
allow
, который включает условие, разрешающее запрос, если его значение истинно.
Каждая из этих концепций более подробно описана ниже.
Cloud Storage
Firebase Security Rules в Cloud Firestore и Cloud Storage используют следующую структуру и синтаксис:
service <<name>> {
// Match the resource path.
match <<path>> {
// Allow the request if the following conditions are true.
allow <<methods>> : if <<condition>>
}
}
При разработке правил важно понимать следующие ключевые понятия:
- Запрос: метод или методы, вызываемые в операторе
allow
. Это методы, которые вы разрешаете запускать. Стандартные методы:get
,list
,create
,update
иdelete
. Удобные методыread
иwrite
обеспечивают широкий доступ для чтения и записи в указанной базе данных или пути хранения. - Путь: база данных или место хранения, представленное в виде пути URI.
- Правило: оператор
allow
, который включает условие, разрешающее запрос, если его значение истинно.
Каждая из этих концепций более подробно описана ниже.
Realtime Database
В Realtime Database Firebase Security Rules состоят из выражений, подобных JavaScript, содержащихся в документе JSON.
Они используют следующий синтаксис:
{
"rules": {
"<<path>>": {
// Allow the request if the condition for each method is true.
".read": <<condition>>,
".write": <<condition>>,
".validate": <<condition>>
}
}
}
В правиле есть три основных элемента:
- Путь: расположение базы данных. Это отражает структуру JSON вашей базы данных.
- Запрос: это методы, которые правило использует для предоставления доступа. Правила
read
иwrite
предоставляют широкий доступ для чтения и записи, а правилаvalidate
действуют как вторичная проверка для предоставления доступа на основе входящих или существующих данных. - Условие: условие, которое разрешает запрос, если его значение истинно.
Конструкции правил
Cloud Firestore
Основные элементы правила в Cloud Firestore и Cloud Storage следующие:
- Декларация
service
: объявляет продукт Firebase, к которому применяются правила. - Блок
match
: определяет путь в базе данных или сегменте хранилища, к которому применяются правила. - Оператор
allow
: предоставляет условия предоставления доступа, различающиеся по методам. Поддерживаемые методы включают:get
,list
,create
,update
,delete
, а также удобные методыread
иwrite
. - Необязательные объявления
function
: предоставьте возможность комбинировать и обертывать условия для использования в нескольких правилах.
service
содержит один или несколько блоков match
с операторами allow
, предоставляющими условия предоставления доступа к запросам. Переменные request
и resource
доступны для использования в условиях правила. Язык Firebase Security Rules также поддерживает объявления function
.
Версия синтаксиса
Оператор syntax
указывает версию языка правил Firebase, использованного для написания источника. Последняя версия языка — v2
.
rules_version = '2';
service cloud.firestore {
...
}
Если оператор rules_version
не указан, ваши правила будут оцениваться с использованием механизма v1
.
Услуга
Декларация service
определяет, к какому продукту или услуге Firebase применяются ваши правила. Вы можете включить только одно объявление service
в исходный файл.
Cloud Firestore
service cloud.firestore {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Cloud Storage
service firebase.storage {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Если вы определяете правила как для Cloud Firestore , так и для Cloud Storage с помощью интерфейса командной строки Firebase , вам придется хранить их в отдельных файлах.
Соответствовать
Блок match
объявляет шаблон path
, который сопоставляется с путем для запрошенной операции (входящий request.path
). Тело match
должно содержать один или несколько вложенных блоков match
, операторов allow
или объявлений function
. Путь во вложенных блоках match
указывается относительно пути в родительском блоке match
.
Шаблон path
— это имя, подобное каталогу, которое может включать переменные или подстановочные знаки. Шаблон path
допускает совпадение сегментов с одним и несколькими путями. Любые переменные, связанные с path
видны в области match
или любой вложенной области, где объявлен path
.
Совпадения с шаблоном path
могут быть частичными или полными:
- Частичные совпадения: шаблон
path
представляет собой совпадение префиксаrequest.path
. - Полные совпадения: шаблон
path
соответствует всемуrequest.path
.
При полном совпадении оцениваются правила внутри блока. При частичном совпадении проверяются вложенные правила match
, чтобы определить, завершит ли совпадение какой-либо вложенный path
.
Правила в каждом полном match
оцениваются, чтобы определить, разрешить ли запрос. Если какое-либо соответствующее правило предоставляет доступ, запрос разрешается. Если ни одно соответствующее правило не предоставляет доступ, запрос отклоняется.
// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
// Partial match.
match /example/{singleSegment} { // `singleSegment` == 'hello'
allow write; // Write rule not evaluated.
// Complete match.
match /nested/path { // `singleSegment` visible in scope.
allow read; // Read rule is evaluated.
}
}
// Complete match.
match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
allow read; // Read rule is evaluated.
}
}
Как показано в приведенном выше примере, объявления path
поддерживают следующие переменные:
- Односегментный подстановочный знак: переменная подстановочного знака объявляется в пути путем заключения переменной в фигурные скобки:
{variable}
. Эта переменная доступна в оператореmatch
какstring
. - Рекурсивный подстановочный знак: рекурсивный или многосегментный подстановочный знак соответствует нескольким сегментам пути на пути или под ним. Этот подстановочный знак соответствует всем путям ниже заданного вами местоположения. Вы можете объявить это, добавив строку
=**
в конец переменной сегмента:{variable=**}
. Эта переменная доступна в оператореmatch
как объектpath
.
Позволять
Блок match
содержит один или несколько операторов allow
. Это ваши настоящие правила. Вы можете применить allow
правила к одному или нескольким методам. Условия оператора allow
должны иметь значение true, чтобы Cloud Firestore или Cloud Storage могли удовлетворить любой входящий запрос. Вы также можете писать операторы allow
без условий, например, allow read
. Однако если оператор allow
не включает условие, он всегда разрешает запрос этого метода.
Если какое-либо из allow
правил для метода удовлетворено, запрос разрешается. Кроме того, если более широкое правило предоставляет доступ, Rules предоставляют доступ и игнорируют более детальные правила, которые могут ограничивать доступ.
Рассмотрим следующий пример, где любой пользователь может читать или удалять любые свои файлы. Более детальное правило разрешает запись только в том случае, если пользователь, запрашивающий запись, владеет файлом и файл имеет формат PNG. Пользователь может удалить любые файлы в подпути — даже если они не являются PNG — поскольку предыдущее правило это разрешает.
service firebase.storage {
// Allow the requestor to read or delete any resource on a path under the
// user directory.
match /users/{userId}/{anyUserFile=**} {
allow read, delete: if request.auth != null && request.auth.uid == userId;
}
// Allow the requestor to create or update their own images.
// When 'request.method' == 'delete' this rule and the one matching
// any path under the user directory would both match and the `delete`
// would be permitted.
match /users/{userId}/images/{imageId} {
// Whether to permit the request depends on the logical OR of all
// matched rules. This means that even if this rule did not explicitly
// allow the 'delete' the earlier rule would have.
allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
}
}
Метод
Каждый оператор allow
включает в себя метод, который предоставляет доступ для входящих запросов того же метода.
Метод | Тип запроса |
---|---|
Удобные методы | |
read | Любой тип запроса на чтение |
write | Любой тип запроса на запись |
Стандартные методы | |
get | Запросы на чтение отдельных документов или файлов |
list | Чтение запросов на запросы и коллекции |
create | Запись новых документов или файлов |
update | Запись в существующие документы базы данных или обновление метаданных файлов. |
delete | Удалить данные |
Вы не можете перекрывать методы чтения в одном и том же блоке match
или конфликтующие методы записи в одном объявлении path
.
Например, следующие правила не будут выполнены:
service bad.example {
match /rules/with/overlapping/methods {
// This rule allows reads to all authenticated users
allow read: if request.auth != null;
match another/subpath {
// This secondary, more specific read rule causes an error
allow get: if request.auth != null && request.auth.uid == "me";
// Overlapping write methods in the same path cause an error as well
allow write: if request.auth != null;
allow create: if request.auth != null && request.auth.uid == "me";
}
}
}
Функция
Поскольку ваши правила безопасности становятся более сложными, вы можете захотеть обернуть наборы условий в функции, которые вы сможете повторно использовать в своем наборе правил. Правила безопасности поддерживают пользовательские функции. Синтаксис пользовательских функций немного похож на JavaScript, но функции правил безопасности написаны на предметно-ориентированном языке, который имеет некоторые важные ограничения:
- Функции могут содержать только один оператор
return
. Они не могут содержать никакой дополнительной логики. Например, они не могут выполнять циклы или вызывать внешние службы. - Функции могут автоматически получать доступ к функциям и переменным из области, в которой они определены. Например, функция, определенная в области видимости
service cloud.firestore
, имеет доступ к переменнойresource
и встроенным функциям, таким какget()
иexists()
. - Функции могут вызывать другие функции, но не могут выполняться рекурсивно. Общая глубина стека вызовов ограничена 20.
- В правилах версии
v2
функции могут определять переменные с помощью ключевого словаlet
. Функции могут иметь до 10 привязок let, но должны заканчиваться оператором return.
Функция определяется ключевым словом function
и принимает ноль или более аргументов. Например, вы можете объединить два типа условий, использованных в примерах выше, в одну функцию:
service cloud.firestore {
match /databases/{database}/documents {
// True if the user is signed in or the requested data is 'public'
function signedInOrPublic() {
return request.auth.uid != null || resource.data.visibility == 'public';
}
match /cities/{city} {
allow read, write: if signedInOrPublic();
}
match /users/{user} {
allow read, write: if signedInOrPublic();
}
}
}
Вот пример, показывающий аргументы функции и назначения let. Операторы присваивания Let должны быть разделены точкой с запятой.
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
return isAuthor || isAdmin;
}
Обратите внимание, как назначение isAdmin
обеспечивает поиск коллекции администраторов. Для отложенных вычислений без необходимости ненужных поисков воспользуйтесь преимуществами короткого замыкания &&
(AND) и ||
(ИЛИ) сравнения для вызова второй функции только в том случае, если значение isAuthor
равно true (для сравнений &&
) или false (для сравнений ||
).
function isAdmin(userId) {
return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
// `||` is short-circuiting; isAdmin called only if isAuthor == false.
return isAuthor || isAdmin(userId);
}
Использование функций в правилах безопасности делает их более удобными в обслуживании по мере роста сложности правил.
Cloud Storage
Основные элементы правила в Cloud Firestore и Cloud Storage следующие:
- Декларация
service
: объявляет продукт Firebase, к которому применяются правила. - Блок
match
: определяет путь в базе данных или сегменте хранилища, к которому применяются правила. - Оператор
allow
: предоставляет условия предоставления доступа, различающиеся по методам. Поддерживаемые методы включают:get
,list
,create
,update
,delete
, а также удобные методыread
иwrite
. - Необязательные объявления
function
: предоставьте возможность комбинировать и обертывать условия для использования в нескольких правилах.
service
содержит один или несколько блоков match
с операторами allow
, предоставляющими условия предоставления доступа к запросам. Переменные request
и resource
доступны для использования в условиях правила. Язык Firebase Security Rules также поддерживает объявления function
.
Версия синтаксиса
Оператор syntax
указывает версию языка правил Firebase, использованного для написания источника. Последняя версия языка — v2
.
rules_version = '2';
service cloud.firestore {
...
}
Если оператор rules_version
не указан, ваши правила будут оцениваться с использованием механизма v1
.
Услуга
Декларация service
определяет, к какому продукту или услуге Firebase применяются ваши правила. Вы можете включить только одно объявление service
в исходный файл.
Cloud Firestore
service cloud.firestore {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Cloud Storage
service firebase.storage {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Если вы определяете правила как для Cloud Firestore , так и для Cloud Storage с помощью интерфейса командной строки Firebase , вам придется хранить их в отдельных файлах.
Соответствовать
Блок match
объявляет шаблон path
, который сопоставляется с путем для запрошенной операции (входящий request.path
). Тело match
должно содержать один или несколько вложенных блоков match
, операторов allow
или объявлений function
. Путь во вложенных блоках match
указывается относительно пути в родительском блоке match
.
Шаблон path
— это имя, подобное каталогу, которое может включать переменные или подстановочные знаки. Шаблон path
допускает совпадение сегментов с одним и несколькими путями. Любые переменные, связанные с path
видны в области match
или любой вложенной области, где объявлен path
.
Совпадения с шаблоном path
могут быть частичными или полными:
- Частичные совпадения: шаблон
path
представляет собой совпадение префиксаrequest.path
. - Полные совпадения: шаблон
path
соответствует всемуrequest.path
.
При полном совпадении оцениваются правила внутри блока. При частичном совпадении проверяются вложенные правила match
, чтобы определить, завершит ли совпадение какой-либо вложенный path
.
Правила в каждом полном match
оцениваются, чтобы определить, разрешить ли запрос. Если какое-либо соответствующее правило предоставляет доступ, запрос разрешается. Если ни одно соответствующее правило не предоставляет доступ, запрос отклоняется.
// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
// Partial match.
match /example/{singleSegment} { // `singleSegment` == 'hello'
allow write; // Write rule not evaluated.
// Complete match.
match /nested/path { // `singleSegment` visible in scope.
allow read; // Read rule is evaluated.
}
}
// Complete match.
match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
allow read; // Read rule is evaluated.
}
}
Как показано в приведенном выше примере, объявления path
поддерживают следующие переменные:
- Односегментный подстановочный знак: переменная подстановочного знака объявляется в пути путем заключения переменной в фигурные скобки:
{variable}
. Эта переменная доступна в оператореmatch
какstring
. - Рекурсивный подстановочный знак: рекурсивный или многосегментный подстановочный знак соответствует нескольким сегментам пути на пути или под ним. Этот подстановочный знак соответствует всем путям ниже заданного вами местоположения. Вы можете объявить это, добавив строку
=**
в конец переменной сегмента:{variable=**}
. Эта переменная доступна в оператореmatch
как объектpath
.
Позволять
Блок match
содержит один или несколько операторов allow
. Это ваши настоящие правила. Вы можете применить allow
правила к одному или нескольким методам. Условия оператора allow
должны иметь значение true, чтобы Cloud Firestore или Cloud Storage могли удовлетворить любой входящий запрос. Вы также можете писать операторы allow
без условий, например, allow read
. Однако если оператор allow
не включает условие, он всегда разрешает запрос этого метода.
Если какое-либо из allow
правил для метода удовлетворено, запрос разрешается. Кроме того, если более широкое правило предоставляет доступ, Rules предоставляют доступ и игнорируют более детальные правила, которые могут ограничивать доступ.
Рассмотрим следующий пример, где любой пользователь может читать или удалять любые свои файлы. Более детальное правило разрешает запись только в том случае, если пользователь, запрашивающий запись, владеет файлом и файл имеет формат PNG. Пользователь может удалить любые файлы в подпути — даже если они не являются PNG — поскольку предыдущее правило это разрешает.
service firebase.storage {
// Allow the requestor to read or delete any resource on a path under the
// user directory.
match /users/{userId}/{anyUserFile=**} {
allow read, delete: if request.auth != null && request.auth.uid == userId;
}
// Allow the requestor to create or update their own images.
// When 'request.method' == 'delete' this rule and the one matching
// any path under the user directory would both match and the `delete`
// would be permitted.
match /users/{userId}/images/{imageId} {
// Whether to permit the request depends on the logical OR of all
// matched rules. This means that even if this rule did not explicitly
// allow the 'delete' the earlier rule would have.
allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
}
}
Метод
Каждый оператор allow
включает в себя метод, который предоставляет доступ для входящих запросов того же метода.
Метод | Тип запроса |
---|---|
Удобные методы | |
read | Любой тип запроса на чтение |
write | Любой тип запроса на запись |
Стандартные методы | |
get | Запросы на чтение отдельных документов или файлов |
list | Чтение запросов на запросы и коллекции |
create | Запись новых документов или файлов |
update | Запись в существующие документы базы данных или обновление метаданных файлов. |
delete | Удалить данные |
Вы не можете перекрывать методы чтения в одном и том же блоке match
или конфликтующие методы записи в одном объявлении path
.
Например, следующие правила не будут выполнены:
service bad.example {
match /rules/with/overlapping/methods {
// This rule allows reads to all authenticated users
allow read: if request.auth != null;
match another/subpath {
// This secondary, more specific read rule causes an error
allow get: if request.auth != null && request.auth.uid == "me";
// Overlapping write methods in the same path cause an error as well
allow write: if request.auth != null;
allow create: if request.auth != null && request.auth.uid == "me";
}
}
}
Функция
Поскольку ваши правила безопасности становятся более сложными, вы можете захотеть обернуть наборы условий в функции, которые вы сможете повторно использовать в своем наборе правил. Правила безопасности поддерживают пользовательские функции. Синтаксис пользовательских функций немного похож на JavaScript, но функции правил безопасности написаны на предметно-ориентированном языке, который имеет некоторые важные ограничения:
- Функции могут содержать только один оператор
return
. Они не могут содержать никакой дополнительной логики. Например, они не могут выполнять циклы или вызывать внешние службы. - Функции могут автоматически получать доступ к функциям и переменным из области, в которой они определены. Например, функция, определенная в области видимости
service cloud.firestore
, имеет доступ к переменнойresource
и встроенным функциям, таким какget()
иexists()
. - Функции могут вызывать другие функции, но не могут выполняться рекурсивно. Общая глубина стека вызовов ограничена 20.
- В правилах версии
v2
функции могут определять переменные с помощью ключевого словаlet
. Функции могут иметь до 10 привязок let, но должны заканчиваться оператором return.
Функция определяется ключевым словом function
и принимает ноль или более аргументов. Например, вы можете объединить два типа условий, использованных в примерах выше, в одну функцию:
service cloud.firestore {
match /databases/{database}/documents {
// True if the user is signed in or the requested data is 'public'
function signedInOrPublic() {
return request.auth.uid != null || resource.data.visibility == 'public';
}
match /cities/{city} {
allow read, write: if signedInOrPublic();
}
match /users/{user} {
allow read, write: if signedInOrPublic();
}
}
}
Вот пример, показывающий аргументы функции и назначения let. Операторы присваивания Let должны быть разделены точкой с запятой.
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
return isAuthor || isAdmin;
}
Обратите внимание, как назначение isAdmin
обеспечивает поиск коллекции администраторов. Для отложенных вычислений без необходимости ненужных поисков воспользуйтесь преимуществами короткого замыкания &&
(AND) и ||
(ИЛИ) сравнения для вызова второй функции только в том случае, если значение isAuthor
равно true (для сравнений &&
) или false (для сравнений ||
).
function isAdmin(userId) {
return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
// `||` is short-circuiting; isAdmin called only if isAuthor == false.
return isAuthor || isAdmin(userId);
}
Использование функций в правилах безопасности делает их более удобными в обслуживании по мере роста сложности правил.
Realtime Database
Как указано выше, Rules Realtime Database включают три основных элемента: расположение базы данных как зеркало структуры JSON базы данных, тип запроса и условие предоставления доступа.
Расположение базы данных
Структура ваших правил должна соответствовать структуре данных, которые вы храните в своей базе данных. Например, в приложении чата со списком сообщений у вас могут быть такие данные:
{
"messages": {
"message0": {
"content": "Hello",
"timestamp": 1405704370369
},
"message1": {
"content": "Goodbye",
"timestamp": 1405704395231
},
...
}
}
Ваши правила должны отражать эту структуру. Например:
{
"rules": {
"messages": {
"$message": {
// only messages from the last ten minutes can be read
".read": "data.child('timestamp').val() > (now - 600000)",
// new messages must have a string content and a number timestamp
".validate": "newData.hasChildren(['content', 'timestamp']) &&
newData.child('content').isString() &&
newData.child('timestamp').isNumber()"
}
}
}
}
Как показано в приведенном выше примере, Rules Realtime Database поддерживают переменную $location
для сопоставления сегментов пути. Используйте префикс $
перед сегментом пути, чтобы сопоставить правило с любыми дочерними узлами на пути.
{
"rules": {
"rooms": {
// This rule applies to any child of /rooms/, the key for each room id
// is stored inside $room_id variable for reference
"$room_id": {
"topic": {
// The room's topic can be changed if the room id has "public" in it
".write": "$room_id.contains('public')"
}
}
}
}
}
Вы также можете использовать $variable
параллельно с именами констант.
{
"rules": {
"widget": {
// a widget can have a title or color attribute
"title": { ".validate": true },
"color": { ".validate": true },
// but no other child paths are allowed
// in this case, $other means any key excluding "title" and "color"
"$other": { ".validate": false }
}
}
}
Метод
В Realtime Database существует три типа правил. Два из этих типов правил — read
и write
— применяются к методу входящего запроса. Тип правила validate
обеспечивает соблюдение структур данных и проверяет формат и содержимое данных. Rules запускают правила .validate
после проверки того, что правило .write
предоставляет доступ.
Типы правил | |
---|---|
.читать | Описывает, разрешено ли пользователям читать данные и когда это возможно. |
.писать | Описывает, разрешена ли запись данных и когда это возможно. |
.валидатировать | Определяет, как будет выглядеть правильно отформатированное значение, есть ли у него дочерние атрибуты и тип данных. |
По умолчанию, если правило не разрешает это, доступ по пути запрещен.
Условия строительства
Cloud Firestore
Условие — это логическое выражение, которое определяет, следует ли разрешить или запретить конкретную операцию. Переменные request
и resource
предоставляют контекст для этих условий.
Переменная request
Переменная request
включает в себя следующие поля и соответствующую информацию:
request.auth
Веб-токен JSON (JWT), содержащий учетные данные аутентификации из Firebase Authentication . Токен auth
содержит набор стандартных утверждений и любых пользовательских утверждений, которые вы создаете с помощью Firebase Authentication . Узнайте больше о правилах безопасности и Authentication Firebase Security Rules .
request.method
request.method
может быть любым стандартным методом или пользовательским методом. Удобные методы read
и write
также существуют для упрощения правил записи, которые применяются ко всем стандартным методам только для чтения или ко всем стандартным методам только для записи соответственно.
request.params
request.params
включает в себя любые данные, не связанные конкретно с request.resource
, которые могут быть полезны для оценки. На практике эта карта должна быть пустой для всех стандартных методов и должна содержать нересурсные данные для пользовательских методов. Службы должны быть осторожны, чтобы не переименовывать и не изменять тип каких-либо ключей и значений, представленных в качестве параметров.
request.path
request.path
— это путь к целевому resource
. Путь указывается относительно сервиса. Сегменты пути, содержащие небезопасные для URL-адреса символы, такие как /
закодированы в URL-адресе.
resource
переменная
resource
— это текущее значение в сервисе, представленное в виде карты пар ключ-значение. Ссылка на resource
в условии приведет не более к одному чтению значения из службы. Этот поиск будет учитываться в любой квоте, связанной со службой, для ресурса. Для запросов get
resource
будет учитываться только в квоте при отклонении.
Операторы и приоритет операторов
Используйте приведенную ниже таблицу в качестве справки для операторов и их соответствующего приоритета в Rules для Cloud Firestore и Cloud Storage .
Даны произвольные выражения a
и b
, поле f
и индекс i
.
Оператор | Описание | Ассоциативность |
---|---|---|
a[i] a() af | Индекс, вызов, доступ к полям | слева направо | !a -a | Унарное отрицание | справа налево |
a/ba%ba*b | Мультипликативные операторы | слева направо |
a+b ab | Аддитивные операторы | слева направо |
a>ba>=ba | Реляционные операторы | слева направо |
a in b | Наличие в списке или на карте | слева направо |
a is type | Сравнение типов, где type может быть bool, int, float, число, строка, список, карта, временная метка, продолжительность, путь или широта. | слева направо |
a==ba!=b | Операторы сравнения | слева направо | a && b | Условное И | слева направо |
a || b | Условное ИЛИ | слева направо |
a ? true_value : false_value | Тернарное выражение | слева направо |
Cloud Storage
Условие — это логическое выражение, которое определяет, следует ли разрешить или запретить конкретную операцию. Переменные request
и resource
предоставляют контекст для этих условий.
Переменная request
Переменная request
включает в себя следующие поля и соответствующую информацию:
request.auth
Веб-токен JSON (JWT), содержащий учетные данные аутентификации из Firebase Authentication . Токен auth
содержит набор стандартных утверждений и любых пользовательских утверждений, которые вы создаете с помощью Firebase Authentication . Узнайте больше о правилах безопасности и Authentication Firebase Security Rules .
request.method
request.method
может быть любым стандартным методом или пользовательским методом. Удобные методы read
и write
также существуют для упрощения правил записи, которые применяются ко всем стандартным методам только для чтения или ко всем стандартным методам только для записи соответственно.
request.params
request.params
включает в себя любые данные, не связанные конкретно с request.resource
, которые могут быть полезны для оценки. На практике эта карта должна быть пустой для всех стандартных методов и должна содержать нересурсные данные для пользовательских методов. Службы должны быть осторожны, чтобы не переименовывать и не изменять тип каких-либо ключей и значений, представленных в качестве параметров.
request.path
request.path
— это путь к целевому resource
. Путь указывается относительно сервиса. Сегменты пути, содержащие небезопасные для URL-адреса символы, такие как /
закодированы в URL-адресе.
resource
переменная
resource
— это текущее значение в сервисе, представленное в виде карты пар ключ-значение. Ссылка на resource
в условии приведет не более к одному чтению значения из службы. Этот поиск будет учитываться в любой квоте, связанной со службой, для ресурса. Для запросов get
resource
будет учитываться только в квоте при отклонении.
Операторы и приоритет операторов
Используйте приведенную ниже таблицу в качестве справки для операторов и их соответствующего приоритета в Rules для Cloud Firestore и Cloud Storage .
Даны произвольные выражения a
и b
, поле f
и индекс i
.
Оператор | Описание | Ассоциативность |
---|---|---|
a[i] a() af | Индекс, вызов, доступ к полям | слева направо | !a -a | Унарное отрицание | справа налево |
a/ba%ba*b | Мультипликативные операторы | слева направо |
a+b ab | Аддитивные операторы | слева направо |
a>ba>=ba | Реляционные операторы | слева направо |
a in b | Наличие в списке или на карте | слева направо |
a is type | Сравнение типов, где type может быть bool, int, float, число, строка, список, карта, временная метка, продолжительность, путь или широта. | слева направо |
a==ba!=b | Операторы сравнения | слева направо | a && b | Условное И | слева направо |
a || b | Условное ИЛИ | слева направо |
a ? true_value : false_value | Тернарное выражение | слева направо |
Realtime Database
Условие — это логическое выражение, которое определяет, следует ли разрешить или запретить конкретную операцию. Вы можете определить эти условия в Rules Realtime Database следующими способами.
Предопределенные переменные
Существует ряд полезных предопределенных переменных, к которым можно получить доступ внутри определения правила. Вот краткое описание каждого из них:
Предопределенные переменные | |
---|---|
сейчас | Текущее время в миллисекундах с эпохи Linux. Это особенно хорошо работает для проверки временных меток, созданных с помощью Firebase.database.ServerValue.TIMESTAMP SDK. |
корень | RuleDataSnapshot, представляющий корневой путь в базе данных Firebase, существовавший до попытки операции. |
новые данные | RuleDataSnapshot, представляющий данные в том виде, в котором они будут существовать после предпринятой операции. Он включает в себя новые записываемые данные и существующие данные. |
данные | RuleDataSnapshot, представляющий данные в том виде, в каком они существовали до предпринятой операции. |
$переменные | Путь с подстановочными знаками, используемый для представления идентификаторов и динамических дочерних ключей. |
авторизация | Представляет полезную нагрузку токена прошедшего проверку подлинности пользователя. |
Эти переменные можно использовать где угодно в ваших правилах. Например, приведенные ниже правила безопасности гарантируют, что данные, записываемые в узел /foo/
должны представлять собой строку длиной менее 100 символов:
{ "rules": { "foo": { // /foo is readable by the world ".read": true, // /foo is writable by the world ".write": true, // data written to /foo must be a string less than 100 characters ".validate": "newData.isString() && newData.val().length < 100" } } }
Правила на основе данных
Любые данные в вашей базе данных могут использоваться в ваших правилах. Используя предопределенные переменные root
, data
и newData
, вы можете получить доступ к любому пути, который существовал бы до или после события записи.
Рассмотрим этот пример, который разрешает операции записи, пока значение узла /allow_writes/
равно true
, у родительского узла не установлен флаг readOnly
и во вновь записанных данных есть дочерний узел с именем foo
:
".write": "root.child('allow_writes').val() === true && !data.parent().child('readOnly').exists() && newData.child('foo').exists()"
Правила на основе запросов
Хотя вы не можете использовать правила в качестве фильтров, вы можете ограничить доступ к подмножествам данных, используя параметры запроса в своих правилах. Используйте query.
выражения в ваших правилах для предоставления доступа на чтение или запись на основе параметров запроса.
Например, следующее правило на основе запроса использует правила безопасности на основе пользователей и правила на основе запросов, чтобы ограничить доступ к данным в коллекции baskets
только корзинами покупок, принадлежащими активному пользователю:
"baskets": {
".read": "auth.uid !== null &&
query.orderByChild === 'owner' &&
query.equalTo === auth.uid" // restrict basket access to owner of basket
}
Следующий запрос, включающий параметры запроса в правило, будет успешным:
db.ref("baskets").orderByChild("owner")
.equalTo(auth.currentUser.uid)
.on("value", cb) // Would succeed
Однако запросы, которые не включают параметры в правило, завершатся ошибкой PermissionDenied
:
db.ref("baskets").on("value", cb) // Would fail with PermissionDenied
Вы также можете использовать правила на основе запросов, чтобы ограничить объем данных, загружаемых клиентом посредством операций чтения.
Например, следующее правило ограничивает доступ для чтения только к первым 1000 результатам запроса, упорядоченным по приоритету:
messages: {
".read": "query.orderByKey &&
query.limitToFirst <= 1000"
}
// Example queries:
db.ref("messages").on("value", cb) // Would fail with PermissionDenied
db.ref("messages").limitToFirst(1000)
.on("value", cb) // Would succeed (default order by key)
Следующий query.
выражения доступны в Realtime Database Security Rules .
Выражения правил на основе запросов | ||
---|---|---|
Выражение | Тип | Описание |
query.orderByKey query.orderByPriority query.orderByValue | логическое значение | Верно для запросов, упорядоченных по ключу, приоритету или значению. В противном случае неверно. |
query.orderByChild | нить нулевой | Используйте строку для представления относительного пути к дочернему узлу. Например, query.orderByChild === "address/zip" . Если запрос не упорядочен дочерним узлом, это значение равно нулю. |
запрос.startAt запрос.endAt запрос.equalTo | нить число логическое значение нулевой | Извлекает границы выполняющегося запроса или возвращает значение NULL, если набор границ отсутствует. |
query.limitToFirst query.limitToLast | число нулевой | Получает ограничение на выполнение запроса или возвращает значение NULL, если ограничение не установлено. |
Операторы
Rules Realtime Database поддерживают ряд операторов , которые можно использовать для объединения переменных в операторе условия. Полный список операторов смотрите в справочной документации .
Создание условий
Ваши фактические условия будут различаться в зависимости от доступа, который вы хотите предоставить. Rules намеренно предлагают огромную степень гибкости, поэтому правила вашего приложения в конечном итоге могут быть настолько простыми или сложными, насколько вам нужно.
Некоторые рекомендации по созданию простых, готовых к использованию Rules см. в разделе «Основные правила безопасности» .
, Firebase Security Rules используют гибкие, мощные, настраиваемые языки, которые поддерживают широкий диапазон сложности и детализации. Вы можете сделать свои Rules настолько конкретными или настолько общими, насколько это целесообразно для вашего приложения. Правила Realtime Database используют синтаксис, похожий на JavaScript в структуре JSON. В правилах Cloud Firestore и Cloud Storage используется язык, основанный на языке общих выражений (CEL) , который основан на CEL с операторами match
allow
, поддерживающими условно предоставленный доступ.
Однако, поскольку это специальные языки, существует кривая обучения. Используйте это руководство, чтобы лучше понять язык Rules и глубже погрузиться в более сложные правила.
Выберите продукт, чтобы узнать больше о его правилах.
Базовая структура
Cloud Firestore
Firebase Security Rules в Cloud Firestore и Cloud Storage используют следующую структуру и синтаксис:
service <<name>> {
// Match the resource path.
match <<path>> {
// Allow the request if the following conditions are true.
allow <<methods>> : if <<condition>>
}
}
При разработке правил важно понимать следующие ключевые понятия:
- Запрос: метод или методы, вызываемые в операторе
allow
. Это методы, которые вы разрешаете запускать. Стандартные методы:get
,list
,create
,update
иdelete
. Удобные методыread
иwrite
обеспечивают широкий доступ для чтения и записи в указанной базе данных или пути хранения. - Путь: база данных или место хранения, представленное в виде пути URI.
- Правило: оператор
allow
, который включает условие, разрешающее запрос, если его значение истинно.
Каждая из этих концепций более подробно описана ниже.
Cloud Storage
Firebase Security Rules в Cloud Firestore и Cloud Storage используют следующую структуру и синтаксис:
service <<name>> {
// Match the resource path.
match <<path>> {
// Allow the request if the following conditions are true.
allow <<methods>> : if <<condition>>
}
}
При разработке правил важно понимать следующие ключевые понятия:
- Запрос: метод или методы, вызываемые в операторе
allow
. Это методы, которые вы разрешаете запускать. Стандартные методы:get
,list
,create
,update
иdelete
. Удобные методыread
иwrite
обеспечивают широкий доступ для чтения и записи в указанной базе данных или пути хранения. - Путь: база данных или место хранения, представленное в виде пути URI.
- Правило: оператор
allow
, который включает условие, разрешающее запрос, если его значение истинно.
Каждая из этих концепций более подробно описана ниже.
Realtime Database
В Realtime Database Firebase Security Rules состоят из выражений, подобных JavaScript, содержащихся в документе JSON.
Они используют следующий синтаксис:
{
"rules": {
"<<path>>": {
// Allow the request if the condition for each method is true.
".read": <<condition>>,
".write": <<condition>>,
".validate": <<condition>>
}
}
}
В правиле есть три основных элемента:
- Путь: расположение базы данных. Это отражает структуру JSON вашей базы данных.
- Запрос: это методы, которые правило использует для предоставления доступа. Правила
read
иwrite
предоставляют широкий доступ для чтения и записи, а правилаvalidate
действуют как вторичная проверка для предоставления доступа на основе входящих или существующих данных. - Условие: условие, которое разрешает запрос, если его значение истинно.
Конструкции правил
Cloud Firestore
Основные элементы правила в Cloud Firestore и Cloud Storage следующие:
- Декларация
service
: объявляет продукт Firebase, к которому применяются правила. - Блок
match
: определяет путь в базе данных или сегменте хранилища, к которому применяются правила. - Оператор
allow
: предоставляет условия предоставления доступа, различающиеся по методам. Поддерживаемые методы включают:get
,list
,create
,update
,delete
, а также удобные методыread
иwrite
. - Необязательные объявления
function
: предоставьте возможность комбинировать и обертывать условия для использования в нескольких правилах.
service
содержит один или несколько блоков match
с операторами allow
, предоставляющими условия предоставления доступа к запросам. Переменные request
и resource
доступны для использования в условиях правила. Язык Firebase Security Rules также поддерживает объявления function
.
Версия синтаксиса
Оператор syntax
указывает версию языка правил Firebase, использованного для написания источника. Последняя версия языка — v2
.
rules_version = '2';
service cloud.firestore {
...
}
Если оператор rules_version
не указан, ваши правила будут оцениваться с использованием механизма v1
.
Услуга
Декларация service
определяет, к какому продукту или услуге Firebase применяются ваши правила. В каждый исходный файл можно включить только одно объявление service
.
Cloud Firestore
service cloud.firestore {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Cloud Storage
service firebase.storage {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Если вы определяете правила как для Cloud Firestore , так и для Cloud Storage с помощью интерфейса командной строки Firebase , вам придется хранить их в отдельных файлах.
Соответствовать
Блок match
объявляет шаблон path
, который сопоставляется с путем для запрошенной операции (входящий request.path
). Тело match
должно содержать один или несколько вложенных блоков match
, операторов allow
или объявлений function
. Путь во вложенных блоках match
указывается относительно пути в родительском блоке match
.
Шаблон path
— это имя, подобное каталогу, которое может включать переменные или подстановочные знаки. Шаблон path
допускает совпадение сегментов с одним и несколькими путями. Любые переменные, связанные с path
видны в области match
или любой вложенной области, где объявлен path
.
Совпадения с шаблоном path
могут быть частичными или полными:
- Частичные совпадения: шаблон
path
представляет собой совпадение префиксаrequest.path
. - Полные совпадения: шаблон
path
соответствует всемуrequest.path
.
При полном совпадении оцениваются правила внутри блока. При частичном совпадении проверяются вложенные правила match
, чтобы определить, завершит ли совпадение какой-либо вложенный path
.
Правила в каждом полном match
оцениваются, чтобы определить, разрешить ли запрос. Если какое-либо соответствующее правило предоставляет доступ, запрос разрешается. Если ни одно соответствующее правило не предоставляет доступ, запрос отклоняется.
// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
// Partial match.
match /example/{singleSegment} { // `singleSegment` == 'hello'
allow write; // Write rule not evaluated.
// Complete match.
match /nested/path { // `singleSegment` visible in scope.
allow read; // Read rule is evaluated.
}
}
// Complete match.
match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
allow read; // Read rule is evaluated.
}
}
Как показано в приведенном выше примере, объявления path
поддерживают следующие переменные:
- Односегментный подстановочный знак: переменная подстановочного знака объявляется в пути путем заключения переменной в фигурные скобки:
{variable}
. Эта переменная доступна в оператореmatch
какstring
. - Рекурсивный подстановка: рекурсивный или многосегментный, подстановочный знак соответствует нескольким сегментам пути на пути или ниже. Этот подстановочный знак соответствует всем путям под местом, на которое вы его установили. Вы можете объявить его, добавив строку
=**
в конце переменной сегмента:{variable=**}
. Эта переменная доступна в оператореmatch
в качестве объектаpath
.
Позволять
Блок match
содержит одно или несколько allow
. Это ваши реальные правила. Вы можете применить allow
правил одного или нескольких методов. Условия в соответствии с утверждением allow
должны оцениваться до True для Cloud Firestore или Cloud Storage , чтобы предоставить любой входящий запрос. Например, вы также можете написать allow
без условий, allow read
. Однако, если оператор allow
не включает условие, он всегда позволяет запросить этот метод.
Если какое -либо из правил allow
для метода будет выполнено, запрос разрешен. Кроме того, если более широкое правило предоставляет доступ, Rules предоставляют доступ и игнорируют какие -либо более детальные правила, которые могут ограничить доступ.
Рассмотрим следующий пример, когда любой пользователь может читать или удалять любой из своих собственных файлов. Более детальное правило разрешает записи только в том случае, если пользователь, запрашивающий файл, владеет файлом, а файл - PNG. Пользователь может удалить любые файлы в подстойке - даже если он не PNGS - потому что более раннее правило позволяет.
service firebase.storage {
// Allow the requestor to read or delete any resource on a path under the
// user directory.
match /users/{userId}/{anyUserFile=**} {
allow read, delete: if request.auth != null && request.auth.uid == userId;
}
// Allow the requestor to create or update their own images.
// When 'request.method' == 'delete' this rule and the one matching
// any path under the user directory would both match and the `delete`
// would be permitted.
match /users/{userId}/images/{imageId} {
// Whether to permit the request depends on the logical OR of all
// matched rules. This means that even if this rule did not explicitly
// allow the 'delete' the earlier rule would have.
allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
}
}
Метод
Каждое утверждение allow
включает в себя метод, который предоставляет доступ для входящих запросов того же метода.
Метод | Тип запроса |
---|---|
Удобные методы | |
read | Любой тип запроса на чтение |
write | Любой тип запроса на запись |
Стандартные методы | |
get | Читать запросы на отдельные документы или файлы |
list | Прочитать запросы на запросы и коллекции |
create | Написать новые документы или файлы |
update | Записать в существующие документы базы данных или обновлять метаданные файла |
delete | Удалить данные |
Вы не можете перекрывать методы чтения в одном и том же блоке match
или в противоречивых методах записи в том же объявлении path
.
Например, следующие правила потерпят неудачу:
service bad.example {
match /rules/with/overlapping/methods {
// This rule allows reads to all authenticated users
allow read: if request.auth != null;
match another/subpath {
// This secondary, more specific read rule causes an error
allow get: if request.auth != null && request.auth.uid == "me";
// Overlapping write methods in the same path cause an error as well
allow write: if request.auth != null;
allow create: if request.auth != null && request.auth.uid == "me";
}
}
}
Функция
По мере того, как ваши правила безопасности становятся более сложными, вы можете захотеть обернуть наборы условий в функции, которые вы можете повторно использовать на своем наборе правил. Правила безопасности поддерживают пользовательские функции. Синтаксис для пользовательских функций немного похож на JavaScript, но функции правил безопасности записаны на языке, специфичном для домена, который имеет некоторые важные ограничения:
- Функции могут содержать только один
return
оператор. Они не могут содержать какую -либо дополнительную логику. Например, они не могут выполнять петли или вызовать внешние службы. - Функции могут автоматически получить доступ к функциям и переменным из области, в которой они определены. Например, функция
exists()
get()
вservice cloud.firestore
resource
- Функции могут вызывать другие функции, но не могут повторяться. Общая глубина стека вызовов ограничена 20.
- В версии правил
v2
функции могут определять переменные, используя ключевое словоlet
. Функции могут иметь до 10 привязков, но должны заканчиваться оператором возврата.
Функция определяется с помощью ключевого слова function
и принимает ноль или более аргументов. Например, вы можете объединить два типа условий, используемых в примерах выше, в одну функцию:
service cloud.firestore {
match /databases/{database}/documents {
// True if the user is signed in or the requested data is 'public'
function signedInOrPublic() {
return request.auth.uid != null || resource.data.visibility == 'public';
}
match /cities/{city} {
allow read, write: if signedInOrPublic();
}
match /users/{user} {
allow read, write: if signedInOrPublic();
}
}
}
Вот пример, показывающий аргументы функций и позволяет назначениям. Пусть заявления о присвоении должны быть разделены полуколонами.
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
return isAuthor || isAdmin;
}
Обратите внимание, как задание isAdmin
обеспечивает поиск коллекции администраторов. Для ленивой оценки, не требуя ненужных поисков, воспользуйтесь преимуществами короткого замыкающего характера &&
(и) и ||
(Или) сравнения, чтобы вызвать вторую функцию только в том случае, если isAuthor
показан как TRUE (для &&
сравнения) или false (для сравнения ||
).
function isAdmin(userId) {
return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
// `||` is short-circuiting; isAdmin called only if isAuthor == false.
return isAuthor || isAdmin(userId);
}
Использование функций в ваших правилах безопасности делает их более поддерживаемыми по мере роста сложности ваших правил.
Cloud Storage
Основные элементы правила в Cloud Firestore и Cloud Storage заключаются в следующем:
- Объявление
service
: объявляет продукт Firebase, к которому применяются правила. - Блок
match
: определяет путь в базе данных или ведро для хранения, к которым применяются правила. - Заявление
allow
: обеспечивает условия для предоставления доступа, дифференцированного методами. Поддерживаемые методы включают в себя:get
,list
,create
,update
,delete
и методы удобстваread
иwrite
. - Дополнительные объявления
function
: предоставьте возможность объединять и обернуть условия для использования по нескольким правилам.
service
содержит один или несколько блоков match
с заявлениями allow
, которые предоставляют условия, предоставляющие доступ к запросам. Переменные request
и resource
доступны для использования в условиях правила. Язык Firebase Security Rules также поддерживает function
объявления.
Синтаксическая версия
Оператор syntax
указывает на версию языка правил Firebase, используемой для написания источника. Последняя версия языка - v2
.
rules_version = '2';
service cloud.firestore {
...
}
Если утверждение rules_version
не будет предоставлено, ваши правила будут оцениваться с использованием двигателя v1
.
Услуга
Объявление service
определяет, к какому продукту или услуги Firebase применяются ваши правила. Вы можете включить только одно объявление service
на исходный файл.
Cloud Firestore
service cloud.firestore {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Cloud Storage
service firebase.storage {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Если вы определяете правила как для Cloud Firestore , так и для Cloud Storage используя CLI Firebase , вам придется поддерживать их в отдельных файлах.
Соответствовать
Блок match
объявляет шаблон path
, который сочетается с пути для запрошенной операции (входящий request.path
). Тело match
должно иметь один или несколько вложенных блоков match
, allow
операторы или объявления function
. Путь в вложенных блоках match
относительно пути в родительском блоке match
.
Паттерн path
-это название, похожее на каталог, которое может включать переменные или подстановочные знаки. Паттерн path
позволяет сопоставить сегмент с одним путем и многоцелевой сегмент. Любые переменные, связанные в path
видны в рамках match
или в любой вложенной области, где провозглашается path
.
Совпадения с шаблоном path
могут быть частичными или полными:
- Частичные совпадения: шаблон
path
является префиксом Match ofrequest.path
. - Полные совпадения: шаблон
path
соответствует всемrequest.path
.
Когда выполняется полное совпадение, оцениваются правила в блоке. Когда частичное совпадение сделано, вложенные правила match
проверены, чтобы увидеть, завершит ли какой -либо вложенный path
.
Правила в каждом полном match
оцениваются, чтобы определить, разрешать ли запрос. Если какое -либо соответствующее правило предоставляет доступ, запрос разрешен. Если нет соответствующего правила, запрос отрицается.
// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
// Partial match.
match /example/{singleSegment} { // `singleSegment` == 'hello'
allow write; // Write rule not evaluated.
// Complete match.
match /nested/path { // `singleSegment` visible in scope.
allow read; // Read rule is evaluated.
}
}
// Complete match.
match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
allow read; // Read rule is evaluated.
}
}
Как приведен выше пример, объявления path
подтверждают следующие переменные:
- Односегментный подстановочный знак: переменная подстановочного знака объявляется в пути путем обертывания переменной в кудрявые скобки:
{variable}
. Эта переменная доступна в оператореmatch
в видеstring
. - Рекурсивный подстановка: рекурсивный или многосегментный, подстановочный знак соответствует нескольким сегментам пути на пути или ниже. Этот подстановочный знак соответствует всем путям под местом, на которое вы его установили. Вы можете объявить его, добавив строку
=**
в конце переменной сегмента:{variable=**}
. Эта переменная доступна в оператореmatch
в качестве объектаpath
.
Позволять
Блок match
содержит одно или несколько allow
. Это ваши реальные правила. Вы можете применить allow
правил одного или нескольких методов. Условия в соответствии с утверждением allow
должны оцениваться до True для Cloud Firestore или Cloud Storage , чтобы предоставить любой входящий запрос. Например, вы также можете написать allow
без условий, allow read
. Однако, если оператор allow
не включает условие, он всегда позволяет запросить этот метод.
Если какое -либо из правил allow
для метода будет выполнено, запрос разрешен. Кроме того, если более широкое правило предоставляет доступ, Rules предоставляют доступ и игнорируют какие -либо более детальные правила, которые могут ограничить доступ.
Рассмотрим следующий пример, когда любой пользователь может читать или удалять любой из своих собственных файлов. Более детальное правило разрешает записи только в том случае, если пользователь, запрашивающий файл, владеет файлом, а файл - PNG. Пользователь может удалить любые файлы в подстойке - даже если он не PNGS - потому что более раннее правило позволяет.
service firebase.storage {
// Allow the requestor to read or delete any resource on a path under the
// user directory.
match /users/{userId}/{anyUserFile=**} {
allow read, delete: if request.auth != null && request.auth.uid == userId;
}
// Allow the requestor to create or update their own images.
// When 'request.method' == 'delete' this rule and the one matching
// any path under the user directory would both match and the `delete`
// would be permitted.
match /users/{userId}/images/{imageId} {
// Whether to permit the request depends on the logical OR of all
// matched rules. This means that even if this rule did not explicitly
// allow the 'delete' the earlier rule would have.
allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
}
}
Метод
Каждое утверждение allow
включает в себя метод, который предоставляет доступ для входящих запросов того же метода.
Метод | Тип запроса |
---|---|
Удобные методы | |
read | Любой тип запроса на чтение |
write | Любой тип запроса на запись |
Стандартные методы | |
get | Читать запросы на отдельные документы или файлы |
list | Прочитать запросы на запросы и коллекции |
create | Написать новые документы или файлы |
update | Записать в существующие документы базы данных или обновлять метаданные файла |
delete | Удалить данные |
Вы не можете перекрывать методы чтения в одном и том же блоке match
или в противоречивых методах записи в том же объявлении path
.
Например, следующие правила потерпят неудачу:
service bad.example {
match /rules/with/overlapping/methods {
// This rule allows reads to all authenticated users
allow read: if request.auth != null;
match another/subpath {
// This secondary, more specific read rule causes an error
allow get: if request.auth != null && request.auth.uid == "me";
// Overlapping write methods in the same path cause an error as well
allow write: if request.auth != null;
allow create: if request.auth != null && request.auth.uid == "me";
}
}
}
Функция
По мере того, как ваши правила безопасности становятся более сложными, вы можете захотеть обернуть наборы условий в функции, которые вы можете повторно использовать на своем наборе правил. Правила безопасности поддерживают пользовательские функции. Синтаксис для пользовательских функций немного похож на JavaScript, но функции правил безопасности записаны на языке, специфичном для домена, который имеет некоторые важные ограничения:
- Функции могут содержать только один
return
оператор. Они не могут содержать какую -либо дополнительную логику. Например, они не могут выполнять петли или вызовать внешние службы. - Функции могут автоматически получить доступ к функциям и переменным из области, в которой они определены. Например, функция
exists()
get()
вservice cloud.firestore
resource
- Функции могут вызывать другие функции, но не могут повторяться. Общая глубина стека вызовов ограничена 20.
- В версии правил
v2
функции могут определять переменные, используя ключевое словоlet
. Функции могут иметь до 10 привязков, но должны заканчиваться оператором возврата.
Функция определяется с помощью ключевого слова function
и принимает ноль или более аргументов. Например, вы можете объединить два типа условий, используемых в примерах выше, в одну функцию:
service cloud.firestore {
match /databases/{database}/documents {
// True if the user is signed in or the requested data is 'public'
function signedInOrPublic() {
return request.auth.uid != null || resource.data.visibility == 'public';
}
match /cities/{city} {
allow read, write: if signedInOrPublic();
}
match /users/{user} {
allow read, write: if signedInOrPublic();
}
}
}
Вот пример, показывающий аргументы функций и позволяет назначениям. Пусть заявления о присвоении должны быть разделены полуколонами.
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
return isAuthor || isAdmin;
}
Обратите внимание, как задание isAdmin
обеспечивает поиск коллекции администраторов. Для ленивой оценки, не требуя ненужных поисков, воспользуйтесь преимуществами короткого замыкающего характера &&
(и) и ||
(Или) сравнения, чтобы вызвать вторую функцию только в том случае, если isAuthor
показан как TRUE (для &&
сравнения) или false (для сравнения ||
).
function isAdmin(userId) {
return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
// `||` is short-circuiting; isAdmin called only if isAuthor == false.
return isAuthor || isAdmin(userId);
}
Использование функций в ваших правилах безопасности делает их более поддерживаемыми по мере роста сложности ваших правил.
Realtime Database
Как указано выше, Rules Realtime Database включают три основных элемента: местоположение базы данных в качестве зеркала структуры JSON базы данных, типа запроса и условия предоставления доступа.
Расположение базы данных
Структура ваших правил должна следовать структуре данных, которые вы сохранили в вашей базе данных. Например, в приложении чата со списком сообщений у вас могут быть данные, которые выглядят так:
{
"messages": {
"message0": {
"content": "Hello",
"timestamp": 1405704370369
},
"message1": {
"content": "Goodbye",
"timestamp": 1405704395231
},
...
}
}
Ваши правила должны отражать эту структуру. Например:
{
"rules": {
"messages": {
"$message": {
// only messages from the last ten minutes can be read
".read": "data.child('timestamp').val() > (now - 600000)",
// new messages must have a string content and a number timestamp
".validate": "newData.hasChildren(['content', 'timestamp']) &&
newData.child('content').isString() &&
newData.child('timestamp').isNumber()"
}
}
}
}
Как показано приведенном выше примере, Rules Realtime Database поддерживают переменную A $location
в соответствии с сегментами пути. Используйте префикс $
перед сегментом своего пути, чтобы соответствовать вашим правилу с любыми дочерними узлами вдоль пути.
{
"rules": {
"rooms": {
// This rule applies to any child of /rooms/, the key for each room id
// is stored inside $room_id variable for reference
"$room_id": {
"topic": {
// The room's topic can be changed if the room id has "public" in it
".write": "$room_id.contains('public')"
}
}
}
}
}
Вы также можете использовать $variable
параллельно с именами постоянных путей.
{
"rules": {
"widget": {
// a widget can have a title or color attribute
"title": { ".validate": true },
"color": { ".validate": true },
// but no other child paths are allowed
// in this case, $other means any key excluding "title" and "color"
"$other": { ".validate": false }
}
}
}
Метод
В Realtime Database существует три типа правил. Два из этих типов правил - read
и write
- применить метод входящего запроса. Тип правила validate
обеспечивает соблюдение структур данных и проверяет формат и содержание данных. Rules .validate
.write
Типы правил | |
---|---|
.читать | Описывает, если и когда данные разрешены для чтения пользователями. |
.писать | Описывает, если и когда данные разрешены. |
.validate | Определяет, как будет выглядеть правильно отформатированное значение, есть ли у него атрибуты ребенка, и тип данных. |
По умолчанию, если его не разрешает правило, доступ к пути отрицается.
Условия здания
Cloud Firestore
Условие - это логическое выражение, которое определяет, должна ли конкретная операция быть разрешена или запрещена. Переменные request
и resource
обеспечивают контекст для этих условий.
Переменная request
Переменная request
включает в себя следующие поля и соответствующую информацию:
request.auth
Веб -токен JSON (JWT), который содержит учетные данные аутентификации от Firebase Authentication . auth
Token содержит набор стандартных претензий и любые пользовательские претензии, которые вы создаете с помощью Firebase Authentication . Узнайте больше о Firebase Security Rules и Authentication .
request.method
request.method
может быть любым из стандартных методов или пользовательского метода. Методы удобства read
и write
, чтобы упростить правила письма, которые применяются ко всем только для чтения или всем стандартным методам только для записи соответственно.
request.params
request.params
включают любые данные, не связанные с request.resource
, которые могут быть полезны для оценки. На практике эта карта должна быть пустой для всех стандартных методов и должна содержать данные не ресурсов для пользовательских методов. Службы должны быть осторожны, чтобы не переименовать и не изменять тип любых ключей и значений, представленных как параметры.
request.path
request.path
- это путь для целевого resource
. Путь относится к услуге. Сегменты пути, содержащие невозможные безопасные символы, такие как /
кодируются URL.
Переменная resource
resource
является текущим значением в службе, представленной в виде карты пар клавиш. Ссылка на resource
в условиях приведет к максимум одному чтению значения из Сервиса. Этот поиск будет учитываться против любой квоты, связанной с обслуживанием, для ресурса. Для get
запросов resource
будет учитываться только к квоте в отказе.
Операторы и приоритет оператора
Используйте приведенную ниже таблицу в качестве ссылки для операторов и соответствующего их приоритета в Rules для Cloud Firestore и Cloud Storage .
Учитывая произвольные выражения a
и b
, поле f
и индекс i
.
Оператор | Описание | Ассоциативность |
---|---|---|
a[i] a() af | Индекс, вызов, доступ к полю | слева направо | !a -a | Единое отрицание | справа налево |
a/ba%ba*b | Мультипликативные операторы | слева направо |
a+b ab | Аддитивные операторы | слева направо |
a>ba>=ba | Реляционные операторы | слева направо |
a in b | Существование в списке или карте | слева направо |
a is type | Сравнение типа, где type может быть Bool, Int, Float, Number, String, List, Map, TimeStamp, продолжительность, путь или латлнг | слева направо |
a==ba!=b | Операторы сравнения | слева направо | a && b | Условно и | слева направо |
a || b | Условное или | слева направо |
a ? true_value : false_value | Тройное выражение | слева направо |
Cloud Storage
Условие - это логическое выражение, которое определяет, должна ли конкретная операция быть разрешена или запрещена. Переменные request
и resource
обеспечивают контекст для этих условий.
Переменная request
Переменная request
включает в себя следующие поля и соответствующую информацию:
request.auth
Веб -токен JSON (JWT), который содержит учетные данные аутентификации от Firebase Authentication . auth
Token содержит набор стандартных претензий и любые пользовательские претензии, которые вы создаете с помощью Firebase Authentication . Узнайте больше о Firebase Security Rules и Authentication .
request.method
request.method
может быть любым из стандартных методов или пользовательского метода. Методы удобства read
и write
, чтобы упростить правила письма, которые применяются ко всем только для чтения или всем стандартным методам только для записи соответственно.
request.params
request.params
включают любые данные, не связанные с request.resource
, которые могут быть полезны для оценки. На практике эта карта должна быть пустой для всех стандартных методов и должна содержать данные не ресурсов для пользовательских методов. Службы должны быть осторожны, чтобы не переименовать и не изменять тип любых ключей и значений, представленных как параметры.
request.path
request.path
- это путь для целевого resource
. Путь относится к услуге. Сегменты пути, содержащие невозможные безопасные символы, такие как /
кодируются URL.
Переменная resource
resource
является текущим значением в службе, представленной в виде карты пар клавиш. Ссылка на resource
в условиях приведет к максимум одному чтению значения из Сервиса. Этот поиск будет учитываться против любой квоты, связанной с обслуживанием, для ресурса. Для get
запросов resource
будет учитываться только к квоте в отказе.
Операторы и приоритет оператора
Используйте приведенную ниже таблицу в качестве ссылки для операторов и соответствующего их приоритета в Rules для Cloud Firestore и Cloud Storage .
Учитывая произвольные выражения a
и b
, поле f
и индекс i
.
Оператор | Описание | Ассоциативность |
---|---|---|
a[i] a() af | Индекс, вызов, доступ к полю | слева направо | !a -a | Единое отрицание | справа налево |
a/ba%ba*b | Мультипликативные операторы | слева направо |
a+b ab | Аддитивные операторы | слева направо |
a>ba>=ba | Реляционные операторы | слева направо |
a in b | Существование в списке или карте | слева направо |
a is type | Сравнение типа, где type может быть Bool, Int, Float, Number, String, List, Map, TimeStamp, продолжительность, путь или латлнг | слева направо |
a==ba!=b | Операторы сравнения | слева направо | a && b | Условно и | слева направо |
a || b | Условное или | слева направо |
a ? true_value : false_value | Тройное выражение | слева направо |
Realtime Database
Условие - это логическое выражение, которое определяет, должна ли конкретная операция быть разрешена или запрещена. Вы можете определить эти условия в Rules Realtime Database следующими способами.
Предварительно определенные переменные
Существует ряд полезных, предварительно определенных переменных, которые можно получить внутри определения правила. Вот краткое изложение каждого:
Предопределенные переменные | |
---|---|
сейчас | Текущее время в миллисекундах со времен Epoch Linux. Это особенно хорошо работает для проверки временных метков, созданных с помощью SDK Firebase.database.servervalue.timestamp. |
корень | Управляющий правительством, представляющим корневой путь в базе данных Firebase, когда он существует перед попыткой операции. |
Ньюдата | Управление, представляющее данные, которые будут существовать после попытки операции. Он включает в себя новые данные, написанные и существующие данные. |
данные | Управляющий правительством, представляющим данные, которые существовали до попытки работы. |
$ переменные | Путь с подстановочным знаком, используемый для представления идентификаторов и динамичных детских ключей. |
авторизация | Представляет собой аутентифицированную полезную нагрузку пользователя. |
Эти переменные можно использовать в любом месте ваших правил. Например, приведенные ниже правила безопасности убедитесь, что данные, записанные в /foo/
node, должны быть строкой менее 100 символов:
{ "rules": { "foo": { // /foo is readable by the world ".read": true, // /foo is writable by the world ".write": true, // data written to /foo must be a string less than 100 characters ".validate": "newData.isString() && newData.val().length < 100" } } }
Правила на основе данных
Любые данные в вашей базе данных могут использоваться в ваших правилах. Используя предварительно определенные переменные root
, data
и newData
, вы можете получить доступ к любому пути, как это было бы до или после события записи.
Рассмотрим этот пример, который позволяет операциям записи до тех пор, пока значение /allow_writes/
node является true
, родительский узел не имеет набора флага readOnly
, и в недавно написанных данных есть ребенок foo
именем:
".write": "root.child('allow_writes').val() === true && !data.parent().child('readOnly').exists() && newData.child('foo').exists()"
Правила на основе запросов
Хотя вы не можете использовать правила в качестве фильтров, вы можете ограничить доступ к подмножествам данных, используя параметры запроса в ваших правилах. Используйте query.
Выражения в ваших правилах для предоставления прочтения или записи доступа на основе параметров запроса.
Например, в следующем правиле на основе запросов используются правила безопасности на основе пользователей и правила, основанные на запросах, для ограничения доступа к данным в сборе baskets
только к корзинам для покупок, которыми владеет активный пользователь:
"baskets": {
".read": "auth.uid !== null &&
query.orderByChild === 'owner' &&
query.equalTo === auth.uid" // restrict basket access to owner of basket
}
Следующий запрос, который включает параметры запроса в правиле, будет успешным:
db.ref("baskets").orderByChild("owner")
.equalTo(auth.currentUser.uid)
.on("value", cb) // Would succeed
Тем не менее, запросы, которые не включают параметры в правиле, потерпят неудачу с ошибки PermissionDenied
:
db.ref("baskets").on("value", cb) // Would fail with PermissionDenied
Вы также можете использовать правила, основанные на запросах, чтобы ограничить количество данных, которые клиент загружает с помощью операций чтения.
Например, следующее правило ограничивает доступ только к первым 1000 результатам запроса, как указано по приоритету:
messages: {
".read": "query.orderByKey &&
query.limitToFirst <= 1000"
}
// Example queries:
db.ref("messages").on("value", cb) // Would fail with PermissionDenied
db.ref("messages").limitToFirst(1000)
.on("value", cb) // Would succeed (default order by key)
Следующий query.
Выражения доступны в Realtime Database Security Rules .
Выражения правил на основе запросов | ||
---|---|---|
Выражение | Тип | Описание |
Query.orderbykey Query.orderbypriority Query.orderbyvalue | логическое значение | Верно для запросов, упорядоченных с помощью ключа, приоритета или значения. Неверно иначе. |
Query.orderbychild | нить нулевой | Используйте строку, чтобы представить относительный путь к детскому узлу. Например, query.orderByChild === "address/zip" . Если запрос не заказан детским узлом, это значение является нулевым. |
Query.Startat Query.endat Query.equalto | нить число логическое значение нулевой | Извлекает границы выполняющего запроса или возвращает NULL, если нет связанного набора. |
Query.limittofirst Query.limittolast | число нулевой | Извлекает предел выполнения запроса или возвращает NULL, если нет ограничения. |
Операторы
Rules Realtime Database поддерживают ряд операторов, которые вы можете использовать для объединения переменных в операторе условия. См. Полный список операторов в справочной документации .
Создание условий
Ваши фактические условия будут варьироваться в зависимости от доступа, который вы хотите предоставить. Rules преднамеренно предлагают огромную степень гибкости, поэтому правила вашего приложения в конечном итоге могут быть такими же простыми или сложными, насколько вам нужно.
Для некоторого руководства создают простые, готовые к производству Rules , см. Основные правила безопасности .
, Firebase Security Rules используют гибкие, мощные, пользовательские языки, которые поддерживают широкий спектр сложности и гранулярности. Вы можете сделать свои Rules такими же конкретными или такими же общими, как и для вашего приложения. Правила Realtime Database используют синтаксис, который выглядит как JavaScript в структуре JSON. Правила Cloud Firestore и Cloud Storage используют язык, основанный на общем языке выражения (CEL) , который основан на CEL с match
и allow
утверждениям, которые поддерживают условно предоставляемый доступ.
Однако, поскольку это пользовательские языки, существует кривая обучения. Используйте это руководство, чтобы лучше понять язык Rules , когда вы углубитесь в более сложные правила.
Выберите продукт, чтобы узнать больше о его правилах.
Базовая структура
Cloud Firestore
Firebase Security Rules в Cloud Firestore и Cloud Storage Используйте следующую структуру и синтаксис:
service <<name>> {
// Match the resource path.
match <<path>> {
// Allow the request if the following conditions are true.
allow <<methods>> : if <<condition>>
}
}
Следующие ключевые понятия важны для понимания при создании правил:
- Запрос: метод или методы, вызванные оператором
allow
. Это методы, которые вы позволяете запускать. Стандартные методы:get
,list
,create
,update
иdelete
. Методы удобстваread
иwrite
позволяют широкому прочтению и записи доступа к указанной базе данных или пути хранения. - Путь: база данных или место хранения, представленное в качестве пути URI.
- Правило: утверждение
allow
, которое включает в себя условие, которое разрешает запрос, если оно оценивается на истину.
Каждая из этих концепций описана более подробно ниже.
Cloud Storage
Firebase Security Rules в Cloud Firestore и Cloud Storage Используйте следующую структуру и синтаксис:
service <<name>> {
// Match the resource path.
match <<path>> {
// Allow the request if the following conditions are true.
allow <<methods>> : if <<condition>>
}
}
Следующие ключевые понятия важны для понимания при создании правил:
- Запрос: метод или методы, вызванные оператором
allow
. Это методы, которые вы позволяете запускать. Стандартные методы:get
,list
,create
,update
иdelete
. Методы удобстваread
иwrite
позволяют широкому прочтению и записи доступа к указанной базе данных или пути хранения. - Путь: база данных или место хранения, представленное в качестве пути URI.
- Правило: утверждение
allow
, которое включает в себя условие, которое разрешает запрос, если оно оценивается на истину.
Каждая из этих концепций описана более подробно ниже.
Realtime Database
В Realtime Database Firebase Security Rules состоят из выражений, подобных JavaScript, содержащихся в документе JSON.
Они используют следующий синтаксис:
{
"rules": {
"<<path>>": {
// Allow the request if the condition for each method is true.
".read": <<condition>>,
".write": <<condition>>,
".validate": <<condition>>
}
}
}
В правиле есть три основных элемента:
- Путь: расположение базы данных. Это отражает структуру JSON вашей базы данных.
- Запрос: это методы, которые правило использует для предоставления доступа. Правила
read
иwrite
предоставляют широкий доступ к чтению и записи, в то время какvalidate
правил закона в качестве вторичной проверки для предоставления доступа на основе входящих или существующих данных. - Условие: условие, которое разрешает запрос, если он оценивается на истину.
Правило конструкции
Cloud Firestore
Основные элементы правила в Cloud Firestore и Cloud Storage заключаются в следующем:
- Объявление
service
: объявляет продукт Firebase, к которому применяются правила. - Блок
match
: определяет путь в базе данных или ведро для хранения, к которым применяются правила. - Заявление
allow
: обеспечивает условия для предоставления доступа, дифференцированного методами. Поддерживаемые методы включают в себя:get
,list
,create
,update
,delete
и методы удобстваread
иwrite
. - Дополнительные объявления
function
: предоставьте возможность объединять и обернуть условия для использования по нескольким правилам.
service
содержит один или несколько блоков match
с заявлениями allow
, которые предоставляют условия, предоставляющие доступ к запросам. Переменные request
и resource
доступны для использования в условиях правила. Язык Firebase Security Rules также поддерживает function
объявления.
Синтаксическая версия
Оператор syntax
указывает на версию языка правил Firebase, используемой для написания источника. Последняя версия языка - v2
.
rules_version = '2';
service cloud.firestore {
...
}
Если утверждение rules_version
не будет предоставлено, ваши правила будут оцениваться с использованием двигателя v1
.
Услуга
Объявление service
определяет, к какому продукту или услуги Firebase применяются ваши правила. Вы можете включить только одно объявление service
на исходный файл.
Cloud Firestore
service cloud.firestore {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Cloud Storage
service firebase.storage {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Если вы определяете правила как для Cloud Firestore , так и для Cloud Storage используя CLI Firebase , вам придется поддерживать их в отдельных файлах.
Соответствовать
Блок match
объявляет шаблон path
, который сочетается с пути для запрошенной операции (входящий request.path
). Тело match
должно иметь один или несколько вложенных блоков match
, allow
операторы или объявления function
. Путь в вложенных блоках match
относительно пути в родительском блоке match
.
Паттерн path
-это название, похожее на каталог, которое может включать переменные или подстановочные знаки. Паттерн path
позволяет сопоставить сегмент с одним путем и многоцелевой сегмент. Любые переменные, связанные в path
видны в рамках match
или в любой вложенной области, где провозглашается path
.
Совпадения с шаблоном path
могут быть частичными или полными:
- Частичные совпадения: шаблон
path
является префиксом Match ofrequest.path
. - Полные совпадения: шаблон
path
соответствует всемrequest.path
.
Когда выполняется полное совпадение, оцениваются правила в блоке. Когда частичное совпадение сделано, вложенные правила match
проверены, чтобы увидеть, завершит ли какой -либо вложенный path
.
Правила в каждом полном match
оцениваются, чтобы определить, разрешать ли запрос. Если какое -либо соответствующее правило предоставляет доступ, запрос разрешен. Если нет соответствующего правила, запрос отрицается.
// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
// Partial match.
match /example/{singleSegment} { // `singleSegment` == 'hello'
allow write; // Write rule not evaluated.
// Complete match.
match /nested/path { // `singleSegment` visible in scope.
allow read; // Read rule is evaluated.
}
}
// Complete match.
match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
allow read; // Read rule is evaluated.
}
}
Как приведен выше пример, объявления path
подтверждают следующие переменные:
- Односегментный подстановочный знак: переменная подстановочного знака объявляется в пути путем обертывания переменной в кудрявые скобки:
{variable}
. Эта переменная доступна в оператореmatch
в видеstring
. - Рекурсивный подстановка: рекурсивный или многосегментный, подстановочный знак соответствует нескольким сегментам пути на пути или ниже. Этот подстановочный знак соответствует всем путям под местом, на которое вы его установили. Вы можете объявить его, добавив строку
=**
в конце переменной сегмента:{variable=**}
. Эта переменная доступна в оператореmatch
в качестве объектаpath
.
Позволять
Блок match
содержит одно или несколько allow
. Это ваши реальные правила. Вы можете применить allow
правил одного или нескольких методов. Условия в соответствии с утверждением allow
должны оцениваться до True для Cloud Firestore или Cloud Storage , чтобы предоставить любой входящий запрос. Например, вы также можете написать allow
без условий, allow read
. Однако, если оператор allow
не включает условие, он всегда позволяет запросить этот метод.
Если какое -либо из правил allow
для метода будет выполнено, запрос разрешен. Кроме того, если более широкое правило предоставляет доступ, Rules предоставляют доступ и игнорируют какие -либо более детальные правила, которые могут ограничить доступ.
Рассмотрим следующий пример, когда любой пользователь может читать или удалять любой из своих собственных файлов. Более детальное правило разрешает записи только в том случае, если пользователь, запрашивающий файл, владеет файлом, а файл - PNG. Пользователь может удалить любые файлы в подстойке - даже если он не PNGS - потому что более раннее правило позволяет.
service firebase.storage {
// Allow the requestor to read or delete any resource on a path under the
// user directory.
match /users/{userId}/{anyUserFile=**} {
allow read, delete: if request.auth != null && request.auth.uid == userId;
}
// Allow the requestor to create or update their own images.
// When 'request.method' == 'delete' this rule and the one matching
// any path under the user directory would both match and the `delete`
// would be permitted.
match /users/{userId}/images/{imageId} {
// Whether to permit the request depends on the logical OR of all
// matched rules. This means that even if this rule did not explicitly
// allow the 'delete' the earlier rule would have.
allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
}
}
Метод
Каждое утверждение allow
включает в себя метод, который предоставляет доступ для входящих запросов того же метода.
Метод | Тип запроса |
---|---|
Удобные методы | |
read | Любой тип запроса на чтение |
write | Любой тип запроса на запись |
Стандартные методы | |
get | Читать запросы на отдельные документы или файлы |
list | Прочитать запросы на запросы и коллекции |
create | Написать новые документы или файлы |
update | Записать в существующие документы базы данных или обновлять метаданные файла |
delete | Удалить данные |
Вы не можете перекрывать методы чтения в одном и том же блоке match
или в противоречивых методах записи в том же объявлении path
.
Например, следующие правила потерпят неудачу:
service bad.example {
match /rules/with/overlapping/methods {
// This rule allows reads to all authenticated users
allow read: if request.auth != null;
match another/subpath {
// This secondary, more specific read rule causes an error
allow get: if request.auth != null && request.auth.uid == "me";
// Overlapping write methods in the same path cause an error as well
allow write: if request.auth != null;
allow create: if request.auth != null && request.auth.uid == "me";
}
}
}
Функция
По мере того, как ваши правила безопасности становятся более сложными, вы можете захотеть обернуть наборы условий в функции, которые вы можете повторно использовать на своем наборе правил. Правила безопасности поддерживают пользовательские функции. Синтаксис для пользовательских функций немного похож на JavaScript, но функции правил безопасности записаны на языке, специфичном для домена, который имеет некоторые важные ограничения:
- Функции могут содержать только один
return
оператор. Они не могут содержать какую -либо дополнительную логику. Например, они не могут выполнять петли или вызовать внешние службы. - Функции могут автоматически получить доступ к функциям и переменным из области, в которой они определены. Например, функция
exists()
get()
вservice cloud.firestore
resource
- Функции могут вызывать другие функции, но не могут повторяться. Общая глубина стека вызовов ограничена 20.
- В версии правил
v2
функции могут определять переменные, используя ключевое словоlet
. Функции могут иметь до 10 привязков, но должны заканчиваться оператором возврата.
Функция определяется с помощью ключевого слова function
и принимает ноль или более аргументов. Например, вы можете объединить два типа условий, используемых в примерах выше, в одну функцию:
service cloud.firestore {
match /databases/{database}/documents {
// True if the user is signed in or the requested data is 'public'
function signedInOrPublic() {
return request.auth.uid != null || resource.data.visibility == 'public';
}
match /cities/{city} {
allow read, write: if signedInOrPublic();
}
match /users/{user} {
allow read, write: if signedInOrPublic();
}
}
}
Вот пример, показывающий аргументы функций и позволяет назначениям. Пусть заявления о присвоении должны быть разделены полуколонами.
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
return isAuthor || isAdmin;
}
Обратите внимание, как задание isAdmin
обеспечивает поиск коллекции администраторов. Для ленивой оценки, не требуя ненужных поисков, воспользуйтесь преимуществами короткого замыкающего характера &&
(и) и ||
(Или) сравнения, чтобы вызвать вторую функцию только в том случае, если isAuthor
показан как TRUE (для &&
сравнения) или false (для сравнения ||
).
function isAdmin(userId) {
return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
// `||` is short-circuiting; isAdmin called only if isAuthor == false.
return isAuthor || isAdmin(userId);
}
Использование функций в ваших правилах безопасности делает их более поддерживаемыми по мере роста сложности ваших правил.
Cloud Storage
Основные элементы правила в Cloud Firestore и Cloud Storage заключаются в следующем:
- Объявление
service
: объявляет продукт Firebase, к которому применяются правила. - Блок
match
: определяет путь в базе данных или ведро для хранения, к которым применяются правила. - Заявление
allow
: обеспечивает условия для предоставления доступа, дифференцированного методами. Поддерживаемые методы включают в себя:get
,list
,create
,update
,delete
и методы удобстваread
иwrite
. - Дополнительные объявления
function
: предоставьте возможность объединять и обернуть условия для использования по нескольким правилам.
service
содержит один или несколько блоков match
с заявлениями allow
, которые предоставляют условия, предоставляющие доступ к запросам. Переменные request
и resource
доступны для использования в условиях правила. Язык Firebase Security Rules также поддерживает function
объявления.
Синтаксическая версия
Оператор syntax
указывает на версию языка правил Firebase, используемой для написания источника. Последняя версия языка - v2
.
rules_version = '2';
service cloud.firestore {
...
}
Если утверждение rules_version
не будет предоставлено, ваши правила будут оцениваться с использованием двигателя v1
.
Услуга
Объявление service
определяет, к какому продукту или услуги Firebase применяются ваши правила. Вы можете включить только одно объявление service
на исходный файл.
Cloud Firestore
service cloud.firestore {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Cloud Storage
service firebase.storage {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Если вы определяете правила как для Cloud Firestore , так и для Cloud Storage используя CLI Firebase , вам придется поддерживать их в отдельных файлах.
Соответствовать
Блок match
объявляет шаблон path
, который сочетается с пути для запрошенной операции (входящий request.path
). Тело match
должно иметь один или несколько вложенных блоков match
, allow
операторы или объявления function
. Путь в вложенных блоках match
относительно пути в родительском блоке match
.
Паттерн path
-это название, похожее на каталог, которое может включать переменные или подстановочные знаки. Паттерн path
позволяет сопоставить сегмент с одним путем и многоцелевой сегмент. Любые переменные, связанные в path
видны в рамках match
или в любой вложенной области, где провозглашается path
.
Matches against a path
pattern may be partial or complete:
- Partial matches: The
path
pattern is a prefix-match of therequest.path
. - Complete matches: The
path
pattern matches the entirerequest.path
.
When a complete match is made the rules within the block are evaluated. When a partial match is made the nested match
rules are tested to see whether any nested path
will complete the match.
The rules in each complete match
are evaluated to determine whether to permit the request. If any matching rule grants access, the request is permitted. If no matching rule grants access, the request is denied.
// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
// Partial match.
match /example/{singleSegment} { // `singleSegment` == 'hello'
allow write; // Write rule not evaluated.
// Complete match.
match /nested/path { // `singleSegment` visible in scope.
allow read; // Read rule is evaluated.
}
}
// Complete match.
match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
allow read; // Read rule is evaluated.
}
}
As the example above shows, the path
declarations supports the following variables:
- Single-segment wildcard: A wildcard variable is declared in a path by wrapping a variable in curly braces:
{variable}
. This variable is accessible within thematch
statement as astring
. - Recursive wildcard: The recursive, or multi-segment, wildcard matches multiple path segments at or below a path. This wildcard matches all paths below the location you set it to. You can declare it by adding the
=**
string at the end of your segment variable:{variable=**}
. This variable is accessible within thematch
statement as apath
object.
Позволять
The match
block contains one or more allow
statements. These are your actual rules. You can apply allow
rules to one or more methods. The conditions on an allow
statement must evaluate to true for Cloud Firestore or Cloud Storage to grant any incoming request. You can also write allow
statements without conditions, for example, allow read
. If the allow
statement doesn't include a condition, however, it always allows the request for that method.
If any of the allow
rules for the method are satisfied, the request is allowed. Additionally, if a broader rule grants access, Rules grant access and ignore any more granular rules that might limit access.
Consider the following example, where any user can read or delete any of their own files. A more granular rule only allows writes if the user requesting the write owns the file and the file is a PNG. A user can delete any files at the subpath — even if they're not PNGs — because the earlier rule allows it.
service firebase.storage {
// Allow the requestor to read or delete any resource on a path under the
// user directory.
match /users/{userId}/{anyUserFile=**} {
allow read, delete: if request.auth != null && request.auth.uid == userId;
}
// Allow the requestor to create or update their own images.
// When 'request.method' == 'delete' this rule and the one matching
// any path under the user directory would both match and the `delete`
// would be permitted.
match /users/{userId}/images/{imageId} {
// Whether to permit the request depends on the logical OR of all
// matched rules. This means that even if this rule did not explicitly
// allow the 'delete' the earlier rule would have.
allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
}
}
Метод
Each allow
statement includes a method that grants access for incoming requests of the same method.
Метод | Type of request |
---|---|
Convenience methods | |
read | Any type of read request |
write | Any type of write request |
Standard methods | |
get | Read requests for single documents or files |
list | Read requests for queries and collections |
create | Write new documents or files |
update | Write to existing database documents or update file metadata |
delete | Удалить данные |
You can't overlap read methods in the same match
block or conflicting write methods in the same path
declaration.
For example, the following rules would fail:
service bad.example {
match /rules/with/overlapping/methods {
// This rule allows reads to all authenticated users
allow read: if request.auth != null;
match another/subpath {
// This secondary, more specific read rule causes an error
allow get: if request.auth != null && request.auth.uid == "me";
// Overlapping write methods in the same path cause an error as well
allow write: if request.auth != null;
allow create: if request.auth != null && request.auth.uid == "me";
}
}
}
Функция
As your security rules become more complex, you may want to wrap sets of conditions in functions that you can reuse across your ruleset. Security rules support custom functions. The syntax for custom functions is a bit like JavaScript, but security rules functions are written in a domain-specific language that has some important limitations:
- Functions can contain only a single
return
statement. They cannot contain any additional logic. For example, they cannot execute loops or call external services. - Functions can automatically access functions and variables from the scope in which they are defined. For example, a function defined within the
service cloud.firestore
scope has access to theresource
variable and built-in functions such asget()
andexists()
. - Functions may call other functions but may not recurse. The total call stack depth is limited to 20.
- In rules version
v2
, functions can define variables using thelet
keyword. Functions can have up to 10 let bindings, but must end with a return statement.
A function is defined with the function
keyword and takes zero or more arguments. For example, you may want to combine the two types of conditions used in the examples above into a single function:
service cloud.firestore {
match /databases/{database}/documents {
// True if the user is signed in or the requested data is 'public'
function signedInOrPublic() {
return request.auth.uid != null || resource.data.visibility == 'public';
}
match /cities/{city} {
allow read, write: if signedInOrPublic();
}
match /users/{user} {
allow read, write: if signedInOrPublic();
}
}
}
Here is an example showing function arguments and let assignments. Let assignment statements must be separated by semi-colons.
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
return isAuthor || isAdmin;
}
Note how the isAdmin
assignment enforces a lookup of the admins collection. For lazy evaluation without requiring unneeded lookups, take advantage of the short-circuiting nature of &&
(AND) and ||
(OR) comparisons to call a second function only if isAuthor
is shown to be true (for &&
comparisons) or false (for ||
comparisons).
function isAdmin(userId) {
return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
// `||` is short-circuiting; isAdmin called only if isAuthor == false.
return isAuthor || isAdmin(userId);
}
Using functions in your security rules makes them more maintainable as the complexity of your rules grows.
Realtime Database
As outlined above, Realtime Database Rules include three basic elements: the database location as a mirror of the database's JSON structure, the request type, and the condition granting access.
Database location
The structure of your rules should follow the structure of the data you have stored in your database. For example, in a chat app with a list of messages, you might have data that looks like this:
{
"messages": {
"message0": {
"content": "Hello",
"timestamp": 1405704370369
},
"message1": {
"content": "Goodbye",
"timestamp": 1405704395231
},
...
}
}
Your rules should mirror that structure. Например:
{
"rules": {
"messages": {
"$message": {
// only messages from the last ten minutes can be read
".read": "data.child('timestamp').val() > (now - 600000)",
// new messages must have a string content and a number timestamp
".validate": "newData.hasChildren(['content', 'timestamp']) &&
newData.child('content').isString() &&
newData.child('timestamp').isNumber()"
}
}
}
}
As the example above shows, Realtime Database Rules support a $location
variable to match path segments. Use the $
prefix in front of your path segment to match your rule to any child nodes along the path.
{
"rules": {
"rooms": {
// This rule applies to any child of /rooms/, the key for each room id
// is stored inside $room_id variable for reference
"$room_id": {
"topic": {
// The room's topic can be changed if the room id has "public" in it
".write": "$room_id.contains('public')"
}
}
}
}
}
You can also use the $variable
in parallel with constant path names.
{
"rules": {
"widget": {
// a widget can have a title or color attribute
"title": { ".validate": true },
"color": { ".validate": true },
// but no other child paths are allowed
// in this case, $other means any key excluding "title" and "color"
"$other": { ".validate": false }
}
}
}
Метод
In Realtime Database , there are three types of rules. Two of these rule types — read
and write
— apply to the method of an incoming request. The validate
rule type enforces data structures and validates the format and content of data. Rules run .validate
rules after verifying that a .write
rule grants access.
Rule Types | |
---|---|
.читать | Describes if and when data is allowed to be read by users. |
.писать | Describes if and when data is allowed to be written. |
.validate | Defines what a correctly formatted value will look like, whether it has child attributes, and the data type. |
By default, if there isn't a rule allowing it, access at a path is denied.
Building conditions
Cloud Firestore
A condition is a boolean expression that determines whether a particular operation should be allowed or denied. The request
and resource
variables provide context for those conditions.
The request
variable
The request
variable includes the following fields and corresponding information:
request.auth
A JSON Web Token (JWT) that contains authentication credentials from Firebase Authentication . auth
token contains a set of standard claims and any custom claims you create through Firebase Authentication . Learn more about Firebase Security Rules and Authentication .
request.method
The request.method
may be any of the standard methods or a custom method. The convenience methods read
and write
also exist to simplify writing rules that apply to all read-only or all write-only standard methods respectively.
request.params
The request.params
include any data not specifically related to the request.resource
that might be useful for evaluation. In practice, this map should be empty for all standard methods, and should contain non-resource data for custom methods. Services must be careful not to rename or modify the type of any of the keys and values presented as params.
request.path
The request.path
is the path for the target resource
. The path is relative to the service. Path segments containing non-url safe characters such as /
are url-encoded.
The resource
variable
The resource
is the current value within the service represented as a map of key-value pairs. Referencing resource
within a condition will result in at most one read of the value from the service. This lookup will count against any service-related quota for the resource. For get
requests, the resource
will only count toward quota on deny.
Operators and operator precedence
Use the table below as a reference for operators and their corresponding precedence in Rules for Cloud Firestore and Cloud Storage .
Given arbitrary expressions a
and b
, a field f
, and an index i
.
Оператор | Описание | Associativity |
---|---|---|
a[i] a() af | Index, call, field access | left to right | !a -a | Unary negation | right to left |
a/ba%ba*b | Multiplicative operators | left to right |
a+b ab | Additive operators | left to right |
a>ba>=ba | Relational operators | left to right |
a in b | Existence in list or map | left to right |
a is type | Type comparison, where type can be bool, int, float, number, string, list, map, timestamp, duration, path or latlng | left to right |
a==ba!=b | Comparison operators | left to right | a && b | Conditional AND | left to right |
a || b | Conditional OR | left to right |
a ? true_value : false_value | Ternary expression | left to right |
Cloud Storage
A condition is a boolean expression that determines whether a particular operation should be allowed or denied. The request
and resource
variables provide context for those conditions.
The request
variable
The request
variable includes the following fields and corresponding information:
request.auth
A JSON Web Token (JWT) that contains authentication credentials from Firebase Authentication . auth
token contains a set of standard claims and any custom claims you create through Firebase Authentication . Learn more about Firebase Security Rules and Authentication .
request.method
The request.method
may be any of the standard methods or a custom method. The convenience methods read
and write
also exist to simplify writing rules that apply to all read-only or all write-only standard methods respectively.
request.params
The request.params
include any data not specifically related to the request.resource
that might be useful for evaluation. In practice, this map should be empty for all standard methods, and should contain non-resource data for custom methods. Services must be careful not to rename or modify the type of any of the keys and values presented as params.
request.path
The request.path
is the path for the target resource
. The path is relative to the service. Path segments containing non-url safe characters such as /
are url-encoded.
The resource
variable
The resource
is the current value within the service represented as a map of key-value pairs. Referencing resource
within a condition will result in at most one read of the value from the service. This lookup will count against any service-related quota for the resource. For get
requests, the resource
will only count toward quota on deny.
Operators and operator precedence
Use the table below as a reference for operators and their corresponding precedence in Rules for Cloud Firestore and Cloud Storage .
Given arbitrary expressions a
and b
, a field f
, and an index i
.
Оператор | Описание | Associativity |
---|---|---|
a[i] a() af | Index, call, field access | left to right | !a -a | Unary negation | right to left |
a/ba%ba*b | Multiplicative operators | left to right |
a+b ab | Additive operators | left to right |
a>ba>=ba | Relational operators | left to right |
a in b | Existence in list or map | left to right |
a is type | Type comparison, where type can be bool, int, float, number, string, list, map, timestamp, duration, path or latlng | left to right |
a==ba!=b | Comparison operators | left to right | a && b | Conditional AND | left to right |
a || b | Conditional OR | left to right |
a ? true_value : false_value | Ternary expression | left to right |
Realtime Database
A condition is a boolean expression that determines whether a particular operation should be allowed or denied. You can define those conditions in Realtime Database Rules in the following ways.
Pre-defined variables
There are a number of helpful, pre-defined variables that can be accessed inside a rule definition. Here is a brief summary of each:
Predefined Variables | |
---|---|
сейчас | The current time in milliseconds since Linux epoch. This works particularly well for validating timestamps created with the SDK's firebase.database.ServerValue.TIMESTAMP. |
корень | A RuleDataSnapshot representing the root path in the Firebase database as it exists before the attempted operation. |
newData | A RuleDataSnapshot representing the data as it would exist after the attempted operation. It includes the new data being written and existing data. |
данные | A RuleDataSnapshot representing the data as it existed before the attempted operation. |
$ variables | A wildcard path used to represent ids and dynamic child keys. |
авторизация | Represents an authenticated user's token payload. |
These variables can be used anywhere in your rules. For example, the security rules below ensure that data written to the /foo/
node must be a string less than 100 characters:
{ "rules": { "foo": { // /foo is readable by the world ".read": true, // /foo is writable by the world ".write": true, // data written to /foo must be a string less than 100 characters ".validate": "newData.isString() && newData.val().length < 100" } } }
Data-based rules
Any data in your database can be used in your rules. Using the predefined variables root
, data
, and newData
, you can access any path as it would exist before or after a write event.
Consider this example, which allows write operations as long as the value of the /allow_writes/
node is true
, the parent node does not have a readOnly
flag set, and there is a child named foo
in the newly written data:
".write": "root.child('allow_writes').val() === true && !data.parent().child('readOnly').exists() && newData.child('foo').exists()"
Query-based rules
Although you can't use rules as filters, you can limit access to subsets of data by using query parameters in your rules. Use query.
expressions in your rules to grant read or write access based on query parameters.
For example, the following query-based rule uses user-based security rules and query-based rules to restrict access to data in the baskets
collection to only the shopping baskets the active user owns:
"baskets": {
".read": "auth.uid !== null &&
query.orderByChild === 'owner' &&
query.equalTo === auth.uid" // restrict basket access to owner of basket
}
The following query, which includes the query parameters in the rule, would succeed:
db.ref("baskets").orderByChild("owner")
.equalTo(auth.currentUser.uid)
.on("value", cb) // Would succeed
However, queries that do not include the parameters in the rule would fail with a PermissionDenied
error:
db.ref("baskets").on("value", cb) // Would fail with PermissionDenied
You can also use query-based rules to limit how much data a client downloads through read operations.
For example, the following rule limits read access to only the first 1000 results of a query, as ordered by priority:
messages: {
".read": "query.orderByKey &&
query.limitToFirst <= 1000"
}
// Example queries:
db.ref("messages").on("value", cb) // Would fail with PermissionDenied
db.ref("messages").limitToFirst(1000)
.on("value", cb) // Would succeed (default order by key)
The following query.
expressions are available in Realtime Database Security Rules .
Query-based rule expressions | ||
---|---|---|
Выражение | Тип | Описание |
query.orderByKey query.orderByPriority query.orderByValue | логическое значение | True for queries ordered by key, priority, or value. False otherwise. |
query.orderByChild | нить нулевой | Use a string to represent |