Las Cloud Firestore Security Rules te permiten controlar el acceso a documentos y colecciones en tu base de datos. La sintaxis de reglas flexibles te permite crear reglas que coincidan con todo, desde todas las operaciones de escritura en la base de datos hasta las operaciones en un documento específico.
Esta guía describe la sintaxis básica y la estructura de las reglas de seguridad. Combina esta sintaxis con las condiciones de las reglas de seguridad para crear conjuntos de reglas completos.
Declaración del servicio y la base de datos
Cloud Firestore Security Rules siempre comienza con la siguiente declaración:
service cloud.firestore {
match /databases/{database}/documents {
// ...
}
}
La declaración service cloud.firestore
define el permiso de las reglas en Cloud Firestore, lo que evita conflictos entre Cloud Firestore Security Rules y las reglas de otros productos, como Cloud Storage.
La declaración match /databases/{database}/documents
especifica que las reglas deberían coincidir con cualquier base de datos de Cloud Firestore en el proyecto. Actualmente, cada proyecto tiene solo una base de datos llamada (default)
.
Reglas básicas de lectura y escritura
Las reglas básicas consisten en una declaración match
que especifica la ruta de un documento y una expresión allow
que describe cuándo se permite la lectura de los datos especificados:
service cloud.firestore {
match /databases/{database}/documents {
// Match any document in the 'cities' collection
match /cities/{city} {
allow read: if <condition>;
allow write: if <condition>;
}
}
}
Todas las declaraciones de coincidencia deben apuntar a los documentos, no a las colecciones. Una declaración de coincidencia puede apuntar a un documento específico, como en match /cities/SF
, o usar comodines para apuntar a cualquier documento en la ruta especificada, como en match /cities/{city}
.
En el ejemplo anterior, la declaración de coincidencia usa la sintaxis de comodín {city}
.
Esto significa que la regla se aplica a cualquier documento de la colección cities
, como /cities/SF
o /cities/NYC
. Cuando se evalúan las expresiones allow
en la declaración de coincidencia, la variable city
se convierte en el nombre del documento de la ciudad, como SF
o NYC
.
Operaciones detalladas
En algunas situaciones, es útil desglosar read
y write
en operaciones más detalladas. Por ejemplo, la app podría aplicar condiciones diferentes para crear documentos que para eliminarlos. También, podrías permitir lecturas de un solo documento, pero rechazar las consultas de mayor tamaño.
Una regla read
se puede dividir en get
y list
, mientras que una regla write
se puede dividir en create
, update
y delete
:
service cloud.firestore {
match /databases/{database}/documents {
// A read rule can be divided into get and list rules
match /cities/{city} {
// Applies to single document read requests
allow get: if <condition>;
// Applies to queries and collection read requests
allow list: if <condition>;
}
// A write rule can be divided into create, update, and delete rules
match /cities/{city} {
// Applies to writes to nonexistent documents
allow create: if <condition>;
// Applies to writes to existing documents
allow update: if <condition>;
// Applies to delete operations
allow delete: if <condition>;
}
}
}
Datos jerárquicos
Los datos de Cloud Firestore se organizan en colecciones de documentos y cada documento puede extender la jerarquía a través de subcolecciones. Es importante comprender cómo interactúan las reglas de seguridad con los datos jerárquicos.
Considera la situación en la que cada documento de la colección cities
contiene una subcolección landmarks
. Las reglas de seguridad se aplican solo a la ruta que coincide, por lo que no se aplican los controles de acceso definidos de la colección cities
a la subcolección landmarks
. En cambio, debes escribir reglas explícitas para controlar el acceso a las subcolecciones:
service cloud.firestore {
match /databases/{database}/documents {
match /cities/{city} {
allow read, write: if <condition>;
// Explicitly define rules for the 'landmarks' subcollection
match /landmarks/{landmark} {
allow read, write: if <condition>;
}
}
}
}
Cuando se anidan declaraciones match
, la ruta de la declaración match
interna siempre está relacionada con la ruta de la declaración match
externa. Por lo tanto, los siguientes conjuntos de reglas son equivalentes:
service cloud.firestore {
match /databases/{database}/documents {
match /cities/{city} {
match /landmarks/{landmark} {
allow read, write: if <condition>;
}
}
}
}
service cloud.firestore {
match /databases/{database}/documents {
match /cities/{city}/landmarks/{landmark} {
allow read, write: if <condition>;
}
}
}
Comodines recurrentes
Si quieres usar reglas que se apliquen a una jerarquía de profundidad arbitraria, usa la sintaxis de comodines recurrentes, {name=**}
. Por ejemplo:
service cloud.firestore {
match /databases/{database}/documents {
// Matches any document in the cities collection as well as any document
// in a subcollection.
match /cities/{document=**} {
allow read, write: if <condition>;
}
}
}
Cuando uses esta sintaxis, los comodines disponibles contendrán el
segmento de la ruta que coincide completo, incluso si el documento se ubica en una
subcolección anidada a mayor profundidad. Por ejemplo, las reglas anteriores coincidirían con un documento ubicado en /cities/SF/landmarks/coit_tower
y el valor de la variable document
sería SF/landmarks/coit_tower
.
Sin embargo, ten en cuenta que el comportamiento de los comodines recurrentes depende de la versión de las reglas.
Versión 1
Las reglas de seguridad usan la versión 1 de forma predeterminada. En la versión 1, los comodines recurrentes coinciden con uno o más elementos de ruta. No obstante, no pueden coincidir con una ruta vacía, por lo que match /cities/{city}/{document=**}
coincide con los documentos de las subcolecciones, pero no con los de la colección cities
, mientras que match /cities/{document=**}
coincide con los documentos en la colección cities
y sus subcolecciones.
Los comodines recurrentes deben aparecer al final de una declaración match.
Versión 2
En la versión 2 de las reglas de seguridad, los comodines recurrentes coinciden con cero o más elementos de ruta, por lo que match/cities/{city}/{document=**}
coincide con los documentos de cualquier subcolección o colección de cities
.
Para usar la versión 2, debes agregar rules_version = '2';
en la parte superior de tus reglas de seguridad:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Matches any document in the cities collection as well as any document
// in a subcollection.
match /cities/{city}/{document=**} {
allow read, write: if <condition>;
}
}
}
Puedes tener, como máximo, un comodín recurrente por declaración match, pero, en la versión 2, puedes colocar este comodín en cualquier lugar de la declaración. Por ejemplo:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Matches any document in the songs collection group
match /{path=**}/songs/{song} {
allow read, write: if <condition>;
}
}
}
Debes usar la versión 2 si deseas usar las consultas de grupos de colecciones; consulta cómo proteger las consultas de grupos de colecciones.
Superposiciona declaraciones match
Es posible que un documento coincida con más de una declaración match
. Si varias expresiones allow
coinciden con una solicitud, se permite el acceso siempre que alguna de las condiciones sea true
:
service cloud.firestore {
match /databases/{database}/documents {
// Matches any document in the 'cities' collection.
match /cities/{city} {
allow read, write: if false;
}
// Matches any document in the 'cities' collection or subcollections.
match /cities/{document=**} {
allow read, write: if true;
}
}
}
En el ejemplo anterior, se permitirán todas las lecturas y escrituras en la colección cities
, ya que la segunda regla siempre es true
, incluso si la primera regla siempre es false
.
Límites de las reglas de seguridad
Cuando trabajes con reglas de seguridad, ten en cuenta los siguientes límites:
Límite | Detalles |
---|---|
Cantidad máxima de llamadas exists() , get() y getAfter() por solicitud |
Si se excede alguno de esos límites, se obtiene un error de permiso denegado. Algunas llamadas de acceso a documentos se pueden almacenar en caché, y estas llamadas no cuentan para los límites. |
Profundidad máxima de las declaraciones match anidadas |
10 |
Longitud máxima de la ruta de acceso, en segmentos de ruta, permitida en un conjunto de declaraciones match anidadas: |
100 |
Cantidad máxima de variables de captura de rutas de acceso permitida en un conjunto de instrucciones match anidadas |
20 |
Profundidad máxima de las llamadas a funciones | 20 |
Cantidad máxima de argumentos de funciones | 7 |
Cantidad máxima de vinculaciones a variables let por función |
10 |
Cantidad máxima de llamadas recurrentes o cíclicas a una función | 0 (no permitidas) |
Cantidad máxima de expresiones evaluadas por solicitud | 1,000 |
Tamaño máximo de un conjunto de reglas | Los conjuntos de reglas deben cumplir con dos límites de tamaño:
|
Próximos pasos
- Escribe condiciones personalizadas para las reglas de seguridad
- Consulta la referencia de las reglas de seguridad.