获取我们在 Firebase 峰会上发布的所有信息,了解 Firebase 可如何帮助您加快应用开发速度并满怀信心地运行应用。了解详情

Condiciones de escritura para las reglas de seguridad de Cloud Firestore

Esta guía se basa en la guía de estructuración de reglas de seguridad para mostrar cómo agregar condiciones a sus reglas de seguridad de Cloud Firestore. Si no está familiarizado con los conceptos básicos de las reglas de seguridad de Cloud Firestore, consulte la guía de inicio .

El componente principal de las reglas de seguridad de Cloud Firestore es la condición. Una condición es una expresión booleana que determina si se debe permitir o denegar una operación en particular. Use reglas de seguridad para escribir condiciones que verifiquen la autenticación del usuario, validen los datos entrantes o incluso accedan a otras partes de su base de datos.

Autenticación

Uno de los patrones de reglas de seguridad más comunes es controlar el acceso según el estado de autenticación del usuario. Por ejemplo, es posible que su aplicación desee permitir que solo los usuarios registrados escriban datos:

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;
    }
  }
}

Otro patrón común es asegurarse de que los usuarios solo puedan leer y escribir sus propios datos:

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;
    }
  }
}

Si su aplicación usa Firebase Authentication o Google Cloud Identity Platform , la variable request.auth contiene la información de autenticación para el cliente que solicita los datos. Para obtener más información acerca de request.auth , consulte la documentación de referencia .

Validación de datos

Muchas aplicaciones almacenan información de control de acceso como campos en documentos en la base de datos. Las reglas de seguridad de Cloud Firestore pueden permitir o denegar el acceso de forma dinámica en función de los datos del documento:

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';
    }
  }
}

La variable de resource hace referencia al documento solicitado y resource.data es un mapa de todos los campos y valores almacenados en el documento. Para obtener más información sobre la variable de resource , consulte la documentación de referencia .

Al escribir datos, es posible que desee comparar los datos entrantes con los datos existentes. En este caso, si su conjunto de reglas permite la escritura pendiente, la variable request.resource contiene el estado futuro del documento. Para las operaciones de update que solo modifican un subconjunto de los campos del documento, la variable request.resource contendrá el estado del documento pendiente después de la operación. Puede comprobar los valores de los campos en request.resource para evitar actualizaciones de datos no deseadas o incoherentes:

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;
    }
  }
}

Acceder a otros documentos

Usando las funciones get() y exists() , sus reglas de seguridad pueden evaluar las solicitudes entrantes contra otros documentos en la base de datos. Las funciones get() y exists() esperan rutas de documentos completamente especificadas. Cuando usa variables para construir rutas para get() y exists() , necesita escapar explícitamente de las variables usando la sintaxis $(variable) .

En el siguiente ejemplo, la variable de la database de datos es capturada por la declaración de match /databases/{database}/documents y se usa para formar la ruta:

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
    }
  }
}

Para las escrituras, puede usar la función getAfter() para acceder al estado de un documento después de que se complete una transacción o un lote de escrituras, pero antes de que se confirme la transacción o el lote. Al igual get() , la función getAfter() toma una ruta de documento completamente especificada. Puede usar getAfter() para definir conjuntos de escrituras que deben realizarse juntas como una transacción o un lote.

Acceder a los límites de llamadas

Hay un límite en las llamadas de acceso a documentos por evaluación de conjunto de reglas:

  • 10 para solicitudes de un solo documento y solicitudes de consulta.
  • 20 para lecturas, transacciones y escrituras por lotes de múltiples documentos. El límite anterior de 10 también se aplica a cada operación.

    Por ejemplo, imagine que crea una solicitud de escritura por lotes con 3 operaciones de escritura y que sus reglas de seguridad usan 2 llamadas de acceso a documentos para validar cada escritura. En este caso, cada escritura usa 2 de sus 10 llamadas de acceso y la solicitud de escritura por lotes usa 6 de sus 20 llamadas de acceso.

Exceder cualquiera de los límites da como resultado un error de permiso denegado. Algunas llamadas de acceso a documentos pueden almacenarse en caché y las llamadas almacenadas en caché no cuentan para los límites.

Para obtener una explicación detallada de cómo estos límites afectan las transacciones y las escrituras por lotes, consulte la guía para proteger las operaciones atómicas .

Acceso a llamadas y precios

El uso de estas funciones ejecuta una operación de lectura en su base de datos, lo que significa que se le facturará por leer documentos incluso si sus reglas rechazan la solicitud. Consulte los precios de Cloud Firestore para obtener información de facturación más específica.

Funciones personalizadas

A medida que sus reglas de seguridad se vuelven más complejas, es posible que desee incluir conjuntos de condiciones en funciones que pueda reutilizar en su conjunto de reglas. Las reglas de seguridad admiten funciones personalizadas. La sintaxis de las funciones personalizadas es un poco como JavaScript, pero las funciones de las reglas de seguridad están escritas en un lenguaje específico del dominio que tiene algunas limitaciones importantes:

  • Las funciones pueden contener solo una sola declaración de return . No pueden contener ninguna lógica adicional. Por ejemplo, no pueden ejecutar bucles ni llamar a servicios externos.
  • Las funciones pueden acceder automáticamente a funciones y variables desde el ámbito en el que están definidas. Por ejemplo, una función definida dentro del alcance del service cloud.firestore tiene acceso a la variable de resource y funciones integradas como get() y exists() .
  • Las funciones pueden llamar a otras funciones pero no pueden repetirse. La profundidad total de la pila de llamadas está limitada a 10.
  • En la versión de reglas v2 , las funciones pueden definir variables usando la palabra clave let . Las funciones pueden tener hasta 10 enlaces let, pero deben terminar con una declaración de retorno.

Una función se define con la palabra clave function y toma cero o más argumentos. Por ejemplo, es posible que desee combinar los dos tipos de condiciones utilizadas en los ejemplos anteriores en una sola función:

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();
    }
  }
}

El uso de funciones en sus reglas de seguridad las hace más fáciles de mantener a medida que crece la complejidad de sus reglas.

Las reglas no son filtros

Una vez que asegure sus datos y comience a escribir consultas, tenga en cuenta que las reglas de seguridad no son filtros. No puede escribir una consulta para todos los documentos en una colección y esperar que Cloud Firestore devuelva solo los documentos a los que el cliente actual tiene permiso para acceder.

Por ejemplo, tome la siguiente regla de seguridad:

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';
    }
  }
}

Denegado : esta regla rechaza la siguiente consulta porque el conjunto de resultados puede incluir documentos donde la visibility no es public :

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

Permitido : esta regla permite la siguiente consulta porque la cláusula where("visibility", "==", "public") garantiza que el conjunto de resultados cumple la condición de la regla:

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

Las reglas de seguridad de Cloud Firestore evalúan cada consulta contra su resultado potencial y fallan la solicitud si pudiera devolver un documento que el cliente no tiene permiso para leer. Las consultas deben seguir las restricciones establecidas por sus reglas de seguridad. Para obtener más información sobre consultas y reglas de seguridad, consulte consulta de datos de forma segura .

Próximos pasos