Язык правил безопасности

Firebase Security Rules используют гибкие, мощные, пользовательские языки, которые поддерживают широкий диапазон сложности и детализации. Вы можете сделать свои Rules настолько конкретными или общими, насколько это имеет смысл для вашего приложения. Правила Realtime Database используют синтаксис, который выглядит как JavaScript в структуре JSON. Правила Cloud Firestore и Cloud Storage используют язык, основанный на Common Expression Language (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 Rules, используемую для написания исходного кода. Последняя версия языка — 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 CLI, вам придется хранить их в отдельных файлах.

Соответствовать

Блок 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 для метода удовлетворено, запрос разрешается. Кроме того, если более широкое правило предоставляет доступ, 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 принудительно выполняет поиск коллекции admins. Для ленивой оценки без необходимости ненужных поисков воспользуйтесь преимуществами короткого замыкания сравнений && (AND) и || (OR), чтобы вызывать вторую функцию только в том случае, если 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 Rules, используемую для написания исходного кода. Последняя версия языка — 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 CLI, вам придется хранить их в отдельных файлах.

Соответствовать

Блок 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 для метода удовлетворено, запрос разрешается. Кроме того, если более широкое правило предоставляет доступ, 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 принудительно выполняет поиск коллекции admins. Для ленивой оценки без необходимости ненужных поисков воспользуйтесь преимуществами короткого замыкания сравнений && (AND) и || (OR), чтобы вызывать вторую функцию только в том случае, если 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()"
        }
      }
    }
  }

Как показывает пример выше, Realtime Database Rules поддерживает переменную $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 Web Token (JWT), содержащий учетные данные аутентификации из Firebase Authentication . Токен auth содержит набор стандартных утверждений и любых пользовательских утверждений, которые вы создаете через Firebase Authentication . Узнайте больше о Firebase Security Rules и Authentication Firebase .

request.method

Метод request.method может быть любым из стандартных методов или пользовательским методом. Методы удобства read и write также существуют для упрощения правил записи, которые применяются ко всем стандартным методам только для чтения или ко всем стандартным методам только для записи соответственно.

request.params

request.params включают любые данные, не относящиеся конкретно к request.resource , которые могут быть полезны для оценки. На практике эта карта должна быть пустой для всех стандартных методов и должна содержать нересурсные данные для пользовательских методов. Службы должны быть осторожны, чтобы не переименовывать или не изменять тип любого из ключей и значений, представленных как params.

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, number, string, list, map, timestamp, duration, path или latlng слева направо
a==ba!=b Операторы сравнения слева направо
a && b Условное И слева направо
a || b Условное ИЛИ слева направо
a ? true_value : false_value Троичное выражение слева направо

Cloud Storage

Условие — это логическое выражение, которое определяет, следует ли разрешить или запретить определенную операцию. Переменные request и resource предоставляют контекст для этих условий.

Переменная request

Переменная request включает в себя следующие поля и соответствующую информацию:

request.auth

JSON Web Token (JWT), содержащий учетные данные аутентификации из Firebase Authentication . Токен auth содержит набор стандартных утверждений и любых пользовательских утверждений, которые вы создаете через Firebase Authentication . Узнайте больше о Firebase Security Rules и Authentication Firebase .

request.method

Метод request.method может быть любым из стандартных методов или пользовательским методом. Методы удобства read и write также существуют для упрощения правил записи, которые применяются ко всем стандартным методам только для чтения или ко всем стандартным методам только для записи соответственно.

request.params

request.params включают любые данные, не относящиеся конкретно к request.resource , которые могут быть полезны для оценки. На практике эта карта должна быть пустой для всех стандартных методов и должна содержать нересурсные данные для пользовательских методов. Службы должны быть осторожны, чтобы не переименовывать или не изменять тип любого из ключей и значений, представленных как params.

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, number, string, list, map, timestamp, duration, path или latlng слева направо
a==ba!=b Операторы сравнения слева направо
a && b Условное И слева направо
a || b Условное ИЛИ слева направо
a ? true_value : false_value Троичное выражение слева направо

Realtime Database

Условие — это логическое выражение, которое определяет, следует ли разрешить или запретить определенную операцию. Вы можете определить эти условия в Realtime Database Rules следующими способами.

Предопределенные переменные

Есть ряд полезных, предопределенных переменных, к которым можно получить доступ внутри определения правила. Вот краткое описание каждой из них:

Предопределенные переменные
сейчас Текущее время в миллисекундах с эпохи 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 .

Выражения правил на основе запросов
Выражение Тип Описание
запрос.orderByKey
запрос.orderByPriority
запрос.orderByValue
булев True для запросов, упорядоченных по ключу, приоритету или значению. False в противном случае.
запрос.orderByChild нить
нулевой
Используйте строку для представления относительного пути к дочернему узлу. Например, query.orderByChild === "address/zip" . Если запрос не упорядочен по дочернему узлу, это значение равно null.
запрос.startAt
запрос.endAt
запрос.равно
нить
число
булев
нулевой
Извлекает границы выполняемого запроса или возвращает значение null, если граница не установлена.
запрос.limitToFirst
запрос.limitToLast
число
нулевой
Возвращает ограничение на выполняемый запрос или возвращает значение null, если ограничение не установлено.

Операторы

Realtime Database Rules поддерживает ряд операторов , которые можно использовать для объединения переменных в условном операторе. Полный список операторов см. в справочной документации .

Создание условий

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

Руководство по созданию простых, готовых к использованию Rules см. в разделе Основные правила безопасности .