Правила безопасности Firebase используют гибкие, мощные, настраиваемые языки, которые поддерживают широкий диапазон сложности и детализации. Вы можете сделать свои Правила настолько конкретными или общими, насколько это имеет смысл для вашего приложения. Правила базы данных реального времени используют синтаксис, похожий на JavaScript в структуре JSON. В правилах Cloud Firestore и Cloud Storage используется язык, основанный на Common Expression Language (CEL) , который основан на CEL с match
и allow
, поддерживающими условно предоставленный доступ.
Однако, поскольку это настраиваемые языки, существует кривая обучения. Используйте это руководство, чтобы лучше понять язык правил при более глубоком погружении в более сложные правила.
Выберите продукт, чтобы узнать больше о его правилах.
Базовая структура
Облако Firestore
Правила безопасности Firebase в 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
, который включает условие, разрешающее запрос, если оно оценивается как истинное.
Каждая из этих концепций более подробно описана ниже.
Облачное хранилище
Правила безопасности Firebase в 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
, который включает условие, разрешающее запрос, если оно оценивается как истинное.
Каждая из этих концепций более подробно описана ниже.
База данных реального времени
В базе данных реального времени правила безопасности Firebase состоят из выражений, подобных 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
действуют как вторичная проверка для предоставления доступа на основе входящих или существующих данных. - Условие: условие, которое разрешает запрос, если оно оценивается как истинное.
Конструкции правил
Облако Firestore
Основные элементы правила в Cloud Firestore и Cloud Storage следующие:
- Объявление
service
: объявляет продукт Firebase, к которому применяются правила. - Блок
match
: определяет путь в базе данных или сегменте хранилища, к которому применяются правила. - Оператор
allow
: предоставляет условия для предоставления доступа, дифференцированные по методам. К поддерживаемым методам относятся:get
,list
,create
,update
,delete
, а также удобные методыread
иwrite
. - Необязательные объявления
function
: предоставляют возможность комбинировать и оборачивать условия для использования в нескольких правилах.
service
содержит один или несколько блоков match
с операторами allow
, которые предоставляют условия, предоставляющие доступ к запросам. Переменные request
и resource
доступны для использования в условиях правил. Язык правил безопасности Firebase также поддерживает объявления function
.
Синтаксическая версия
Оператор syntax
указывает версию языка правил Firebase, используемую для написания исходного кода. Последняя версия языка v2
.
rules_version = '2';
service cloud.firestore {
...
}
Если инструкция rules_version
не указана, ваши правила будут оцениваться с использованием движка v1
.
Услуга
Объявление service
определяет, к какому продукту или услуге Firebase применяются ваши правила. Вы можете включить только одно объявление service
в исходный файл.
Облако Firestore
service cloud.firestore {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Облачное хранилище
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
должны оцениваться как истина, чтобы Cloud Firestore или Cloud Storage могли предоставить любой входящий запрос. Вы также можете написать операторы allow
без условий, например, allow read
. Однако, если оператор allow
не включает условие, он всегда разрешает запрос для этого метода.
Если какое-либо из allow
правил для метода удовлетворяется, запрос разрешается. Кроме того, если доступ предоставляется более широким правилом, правила предоставляют доступ и игнорируют более детальные правила, которые могут ограничивать доступ.
Рассмотрим следующий пример, где любой пользователь может прочитать или удалить любой из своих файлов. Более детализированное правило разрешает запись только в том случае, если пользователь, запрашивающий запись, владеет файлом и файлом является 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. Пусть операторы присваивания должны быть разделены точкой с запятой.
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
return isAuthor || isAdmin;
}
Обратите внимание, как назначение isAdmin
обеспечивает поиск коллекции admins. Для ленивых вычислений, не требующих ненужных поисков, воспользуйтесь короткозамкнутым характером &&
(И) и ||
(ИЛИ) сравнения для вызова второй функции только в том случае, если показано, что 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 Firestore и Cloud Storage следующие:
- Объявление
service
: объявляет продукт Firebase, к которому применяются правила. - Блок
match
: определяет путь в базе данных или сегменте хранилища, к которому применяются правила. - Оператор
allow
: предоставляет условия для предоставления доступа, дифференцированные по методам. К поддерживаемым методам относятся:get
,list
,create
,update
,delete
, а также удобные методыread
иwrite
. - Необязательные объявления
function
: предоставляют возможность комбинировать и оборачивать условия для использования в нескольких правилах.
service
содержит один или несколько блоков match
с операторами allow
, которые предоставляют условия, предоставляющие доступ к запросам. Переменные request
и resource
доступны для использования в условиях правил. Язык правил безопасности Firebase также поддерживает объявления function
.
Синтаксическая версия
Оператор syntax
указывает версию языка правил Firebase, используемую для написания исходного кода. Последняя версия языка v2
.
rules_version = '2';
service cloud.firestore {
...
}
Если инструкция rules_version
не указана, ваши правила будут оцениваться с использованием движка v1
.
Услуга
Объявление service
определяет, к какому продукту или услуге Firebase применяются ваши правила. Вы можете включить только одно объявление service
в исходный файл.
Облако Firestore
service cloud.firestore {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Облачное хранилище
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
должны оцениваться как истина, чтобы Cloud Firestore или Cloud Storage могли предоставить любой входящий запрос. Вы также можете написать операторы allow
без условий, например, allow read
. Однако, если оператор allow
не включает условие, он всегда разрешает запрос для этого метода.
Если какое-либо из allow
правил для метода удовлетворяется, запрос разрешается. Кроме того, если доступ предоставляется более широким правилом, правила предоставляют доступ и игнорируют более детальные правила, которые могут ограничивать доступ.
Рассмотрим следующий пример, где любой пользователь может прочитать или удалить любой из своих файлов. Более детализированное правило разрешает запись только в том случае, если пользователь, запрашивающий запись, владеет файлом и файлом является 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. Пусть операторы присваивания должны быть разделены точкой с запятой.
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
return isAuthor || isAdmin;
}
Обратите внимание, как назначение isAdmin
обеспечивает поиск коллекции admins. Для ленивых вычислений, не требующих ненужных поисков, воспользуйтесь короткозамкнутым характером &&
(И) и ||
(ИЛИ) сравнения для вызова второй функции только в том случае, если показано, что 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);
}
Использование функций в ваших правилах безопасности делает их более удобными в сопровождении по мере роста сложности ваших правил.
База данных реального времени
Как указано выше, правила базы данных реального времени включают три основных элемента: расположение базы данных как зеркало структуры 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()"
}
}
}
}
Как показано в приведенном выше примере, правила базы данных реального времени поддерживают переменную $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 }
}
}
}
Метод
В базе данных реального времени существует три типа правил. Два из этих типов правил — read
и write
— применяются к методу входящего запроса. Тип правила validate
применяет структуры данных и проверяет формат и содержимое данных. Правила запускают правила .validate
после проверки того, что правило .write
предоставляет доступ.
Типы правил | |
---|---|
.читать | Описывает, разрешено ли чтение данных пользователям и когда. |
.писать | Описывает, разрешена ли запись данных и когда. |
.подтвердить | Определяет, как будет выглядеть правильно отформатированное значение, есть ли у него дочерние атрибуты и тип данных. |
По умолчанию, если это не разрешено правилом, доступ по пути запрещен.
Условия строительства
Облако Firestore
Условие — это логическое выражение, определяющее, следует ли разрешить или запретить конкретную операцию. Переменные request
и resource
предоставляют контекст для этих условий.
Переменная request
Переменная request
включает следующие поля и соответствующую информацию:
request.auth
Веб-токен JSON (JWT), который содержит учетные данные аутентификации от Firebase Authentication. Токен auth
содержит набор стандартных утверждений и любых настраиваемых утверждений, которые вы создаете с помощью аутентификации Firebase. Узнайте больше о правилах безопасности и аутентификации Firebase .
request.method
request.method
может быть любым из стандартных методов или пользовательским методом. Удобные методы read
и write
также существуют для упрощения правил написания, которые применяются ко всем стандартным методам только для чтения или ко всем стандартным методам только для записи соответственно.
request.params
Параметры request.params
включают любые данные, не относящиеся конкретно к request.resource
, которые могут быть полезны для оценки. На практике эта карта должна быть пустой для всех стандартных методов и должна содержать нересурсные данные для пользовательских методов. Службы должны следить за тем, чтобы не переименовывать и не изменять тип любых ключей и значений, представленных в качестве параметров.
request.path
request.path
— это путь к целевому resource
. Путь указан относительно службы. Сегменты пути, содержащие символы, не являющиеся безопасными для URL-адресов, такие как /
, кодируются в URL-адресе.
Переменная resource
resource
— это текущее значение в службе, представленное в виде карты пар ключ-значение. Ссылка на resource
в условии приведет к не более чем одному чтению значения из службы. Этот поиск будет учитываться в отношении любой квоты, связанной со службой, для ресурса. Для запросов get
resource
будет учитываться в квоте только при отказе.
Операторы и приоритет операторов
Используйте приведенную ниже таблицу в качестве справки по операторам и их соответствующему приоритету в правилах для 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, числом, строкой, списком, картой, меткой времени, продолжительностью, путем или latlng | слева направо |
a==ba!=b | Операторы сравнения | слева направо | a && b | Условное И | слева направо |
a || b | Условное ИЛИ | слева направо |
a ? true_value : false_value | Тернарное выражение | слева направо |
Облачное хранилище
Условие — это логическое выражение, определяющее, следует ли разрешить или запретить конкретную операцию. Переменные request
и resource
предоставляют контекст для этих условий.
Переменная request
Переменная request
включает следующие поля и соответствующую информацию:
request.auth
Веб-токен JSON (JWT), который содержит учетные данные аутентификации от Firebase Authentication. Токен auth
содержит набор стандартных утверждений и любых настраиваемых утверждений, которые вы создаете с помощью аутентификации Firebase. Узнайте больше о правилах безопасности и аутентификации Firebase .
request.method
request.method
может быть любым из стандартных методов или пользовательским методом. Удобные методы read
и write
также существуют для упрощения правил написания, которые применяются ко всем стандартным методам только для чтения или ко всем стандартным методам только для записи соответственно.
request.params
Параметры request.params
включают любые данные, не относящиеся конкретно к request.resource
, которые могут быть полезны для оценки. На практике эта карта должна быть пустой для всех стандартных методов и должна содержать нересурсные данные для пользовательских методов. Службы должны следить за тем, чтобы не переименовывать и не изменять тип любых ключей и значений, представленных в качестве параметров.
request.path
request.path
— это путь к целевому resource
. Путь указан относительно службы. Сегменты пути, содержащие символы, не являющиеся безопасными для URL-адресов, такие как /
, кодируются в URL-адресе.
Переменная resource
resource
— это текущее значение в службе, представленное в виде карты пар ключ-значение. Ссылка на resource
в условии приведет к не более чем одному чтению значения из службы. Этот поиск будет учитываться в отношении любой квоты, связанной со службой, для ресурса. Для запросов get
resource
будет учитываться в квоте только при отказе.
Операторы и приоритет операторов
Используйте приведенную ниже таблицу в качестве справки по операторам и их соответствующему приоритету в правилах для 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, числом, строкой, списком, картой, меткой времени, продолжительностью, путем или latlng | слева направо |
a==ba!=b | Операторы сравнения | слева направо | a && b | Условное И | слева направо |
a || b | Условное ИЛИ | слева направо |
a ? true_value : false_value | Тернарное выражение | слева направо |
База данных реального времени
Условие — это логическое выражение, определяющее, следует ли разрешить или запретить конкретную операцию. Вы можете определить эти условия в правилах базы данных реального времени следующими способами.
Предопределенные переменные
Существует ряд полезных предопределенных переменных, доступ к которым можно получить внутри определения правила. Вот краткое изложение каждого:
Предопределенные переменные | |
---|---|
сейчас | Текущее время в миллисекундах с эпохи Linux. Это особенно хорошо работает для проверки временных меток, созданных с помощью SDK firebase.database.ServerValue.TIMESTAMP. |
корень | 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.
выражения доступны в правилах безопасности базы данных в реальном времени.
Выражения правил на основе запросов | ||
---|---|---|
Выражение | Тип | Описание |
запрос.orderByKey запрос.orderByPriority запрос.orderByValue | логический | True для запросов, упорядоченных по ключу, приоритету или значению. Ложь в противном случае. |
query.orderByChild | нить нулевой | Используйте строку для представления относительного пути к дочернему узлу. Например, query.orderByChild === "address/zip" . Если запрос не упорядочен дочерним узлом, это значение равно null. |
запрос.startAt запрос.endAt query.equalTo | нить число логический нулевой | Извлекает границы выполняемого запроса или возвращает значение null, если набор границ отсутствует. |
запрос.limitToFirst запрос.limitToLast | число нулевой | Получает ограничение на выполняемый запрос или возвращает значение null, если ограничение не установлено. |
Операторы
Правила базы данных реального времени поддерживают ряд операторов , которые можно использовать для объединения переменных в операторе условия. Полный список операторов смотрите в справочной документации .
Создание условий
Ваши фактические условия будут различаться в зависимости от доступа, который вы хотите предоставить. Правила намеренно предлагают огромную степень гибкости, поэтому правила вашего приложения в конечном итоге могут быть настолько простыми или настолько сложными, насколько вам нужно.
Некоторые рекомендации по созданию простых, готовых к использованию правил см. в разделе Основные правила безопасности .