Google is committed to advancing racial equity for Black communities. See how.
Эта страница была переведа с помощью Cloud Translation API.
Switch to English

Написание условий для правил безопасности Cloud Firestore

Это руководство основано на руководстве по структурированию правил безопасности, чтобы показать, как добавить условия в правила безопасности Cloud Firestore. Если вы не знакомы с основами Cloud правил безопасности Firestore см началу работы руководства.

Основным компонентом правил безопасности Cloud Firestore является условие. Условие - это логическое выражение, которое определяет, следует ли разрешить или запретить конкретную операцию. Используйте правила безопасности для написания условий, которые проверяют аутентификацию пользователя, проверяют входящие данные или даже обращаются к другим частям вашей базы данных.

Аутентификация

Одним из наиболее распространенных шаблонов правил безопасности является управление доступом на основе состояния аутентификации пользователя. Например, вашему приложению может потребоваться разрешить запись данных только зарегистрированным пользователям:

 service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to access documents in the "cities" collection
    // only if they are authenticated.
    match /cities/{city} {
      allow read, write: if request.auth != null;
    }
  }
}
 

Другой распространенный шаблон - убедиться, что пользователи могут только читать и записывать свои собственные данные:

 service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure the uid of the requesting user matches name of the user
    // document. The wildcard expression {userId} makes the userId variable
    // available in rules.
    match /users/{userId} {
      allow read, update, delete: if request.auth != null && request.auth.uid == userId;
      allow create: if request.auth != null;
    }
  }
}
 

Если ваше приложение использует Firebase Authentication, переменная request.auth содержит информацию аутентификации для клиента, запрашивающего данные. Для получения дополнительной информации о request.auth см. Справочную документацию .

Валидация данных

Многие приложения хранят информацию контроля доступа в виде полей документов в базе данных. Облачные правила безопасности Firestore могут динамически разрешать или запрещать доступ на основе данных документа:

 service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to read data if the document has the 'visibility'
    // field set to 'public'
    match /cities/{city} {
      allow read: if resource.data.visibility == 'public';
    }
  }
}
 

Переменная resource ссылается на запрошенный документ, а resource.data представляет собой карту всех полей и значений, хранящихся в документе. Для получения дополнительной информации о переменной resource см. Справочную документацию .

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

 service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure all cities have a positive population and
    // the name is not changed
    match /cities/{city} {
      allow update: if request.resource.data.population > 0
                    && request.resource.data.name == resource.data.name;
    }
  }
}
 

Доступ к другим документам

Используя функции get() и exists() , ваши правила безопасности могут сравнивать входящие запросы с другими документами в базе данных. Функции get() и exists() ожидают полностью указанных путей к документам. При использовании переменных для построения путей для get() и exists() вам необходимо явно экранировать переменные, используя синтаксис $(variable)

В приведенном ниже примере переменная database захватывается оператором match match /databases/{database}/documents и используется для формирования пути:

 service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      // Make sure a 'users' document exists for the requesting user before
      // allowing any writes to the 'cities' collection
      allow create: if request.auth != null && exists(/databases/$(database)/documents/users/$(request.auth.uid))

      // Allow the user to delete cities if their user document has the
      // 'admin' field set to 'true'
      allow delete: if request.auth != null && get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true
    }
  }
}
 

Для getAfter() вы можете использовать getAfter() чтобы получить доступ к состоянию документа после завершения транзакции или пакета getAfter() но до фиксации транзакции или пакета. Как и get() , getAfter() принимает полностью указанный путь к документу. Вы можете использовать getAfter() для определения наборов getAfter() которые должны выполняться вместе как транзакция или пакет.

Пределы вызовов

Существует ограничение на количество обращений к документу для каждой оценки набора правил:

  • 10 для запросов одного документа и запросов запросов.
  • 20 для многодокументных операций чтения, транзакций и пакетных записей. Предыдущий предел 10 также применяется к каждой операции.

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

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

Подробное объяснение того, как эти ограничения влияют на транзакции и пакетные записи, см. В руководстве по защите атомарных операций .

Доступ звонки и цены

Использование этих функций выполняет операцию чтения в вашей базе данных, что означает, что вам будет выставлен счет за чтение документов, даже если ваши правила отклонят запрос. См. Цены в Cloud Firestore для более подробной информации о выставлении счетов.

Пользовательские функции

Поскольку ваши правила безопасности становятся более сложными, вы можете захотеть заключить в условия наборы функций, которые вы можете повторно использовать в своем наборе правил. Правила безопасности поддерживают пользовательские функции. Синтаксис для пользовательских функций немного похож на JavaScript, но функции правил безопасности написаны на предметно-ориентированном языке, который имеет некоторые важные ограничения:

  • Функции могут содержать только одну инструкцию return . Они не могут содержать никакой дополнительной логики. Например, они не могут выполнять циклы или вызывать внешние службы.
  • Функции могут автоматически обращаться к функциям и переменным из области, в которой они определены. Например, функция, определенная в области service cloud.firestore имеет доступ к переменной resource и встроенным функциям, таким как get() и exists() .
  • Функции могут вызывать другие функции, но не могут выполнять повторение. Общая глубина стека вызовов ограничена 10.
  • В версии правил 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();
    }
  }
}
 

Использование функций в ваших правилах безопасности делает их более удобными для обслуживания по мере роста сложности ваших правил.

Правила не являются фильтрами

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

Например, возьмите следующее правило безопасности:

 service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to read data if the document has the 'visibility'
    // field set to 'public'
    match /cities/{city} {
      allow read: if resource.data.visibility == 'public';
    }
  }
}
 

Запрещено : это правило отклоняет следующий запрос, поскольку в результирующий набор могут входить документы, для которых visibility не является public :

Web
db.collection("cities").get()
    .then(function(querySnapshot) {
        querySnapshot.forEach(function(doc) {
            console.log(doc.id, " => ", doc.data());
    });
});

Разрешено : Это правило разрешает следующий запрос, потому что предложение where("visibility", "==", "public") гарантирует, что результирующий набор удовлетворяет условию правила:

Web
db.collection("cities").where("visibility", "==", "public").get()
    .then(function(querySnapshot) {
        querySnapshot.forEach(function(doc) {
            console.log(doc.id, " => ", doc.data());
        });
    });

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

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