شروط الكتابة لقواعد أمان Cloud Firestore

يستند هذا الدليل إلى دليل تنظيم قواعد الأمان. لعرض كيفية إضافة شروط إلى Cloud Firestore Security Rules. إذا لم تكن كذلك على دراية بأساسيات Cloud Firestore Security Rules، راجِع البدء الدليل.

الوحدة الأساسية لـ Cloud Firestore Security Rules هي الشرط. حاسمة الشرط هو تعبير منطقي يحدد ما إذا كانت عملية معينة السماح أو الرفض. يمكنك استخدام قواعد الأمان لكتابة الشروط التي فحص مصادقة المستخدم، والتحقق من صحة البيانات الواردة، أو حتى الوصول إلى أجزاء أخرى من قاعدة البيانات لديك.

المصادقة

أحد أنماط قواعد الأمان الأكثر شيوعًا هو التحكم في الوصول استنادًا إلى حالة مصادقة المستخدم. على سبيل المثال، قد يريد تطبيقك السماح فقط المستخدمين الذين سجّلوا الدخول لكتابة البيانات:

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 أو Google Cloud Identity Platform، سيحتوي المتغيّر request.auth على معلومات المصادقة للعميل الذي يطلب البيانات. لمزيد من المعلومات عن request.auth، يُرجى الاطّلاع على مستندات ال reference .

التحقّق من صحة البيانات

تخزِّن العديد من التطبيقات معلومات التحكم بالوصول كحقول في المستندات في قاعدة البيانات. يمكن أن تسمح Cloud Firestore Security Rules بشكل ديناميكي بالوصول أو ترفض الوصول استنادًا إلى data المستند:

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 /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() للوصول إلى حالة المستند بعد اكتمال معاملة أو مجموعة من عمليات الكتابة ولكن قبل إتمام المعاملة أو المجموعة. مثل get()، تستخدم الدالة getAfter() مسار المستند المحدد بالكامل. يمكنك استخدام getAfter() لتحديد مجموعات الكتابة. التي يجب أن تتم معًا كمعاملة أو دُفعة واحدة.

الوصول إلى حدود المكالمات

هناك حدّ أقصى لطلبات الوصول إلى المستندات لكل تقييم مجموعة قواعد:

  • 10 لطلبات مستند واحد وطلبات البحث.
  • و20 للقراءات المتعددة المستندات والمعاملات وعمليات الكتابة المجمّعة. وينطبق الحد السابق البالغ 10 على كل العملية.

    على سبيل المثال، لنفترض أنّك أنشأت طلب كتابة مجمّع يتضمّن 3 عمليات كتابة العمليات وأن قواعد الأمان تستخدم مكالمتَين للوصول إلى مستند من أجل والتحقق من صحة كل كتابة. في هذه الحالة، تستخدم كل عملية كتابة 2 من 10 مكالمات وصول، ويستخدم طلب الكتابة المجمّعة 6 من طلبات الوصول البالغ عددها 20 الاتصالات.

يؤدي تجاوز أي من هذين الحدّين إلى ظهور خطأ "تم رفض الإذن". مستند ما قد يتم تخزين مكالمات الوصول مؤقتًا، ولا يتم احتساب المكالمات المخزنة مؤقتًا ضمن الحدود.

للحصول على شرح تفصيلي لكيفية تأثير هذه الحدود على المعاملات عمليات الكتابة المجمّعة، يمكنك الاطّلاع على دليل تأمين العمليات البسيطة.

الوصول إلى المكالمات والأسعار

يؤدي استخدام هذه الدوال إلى تنفيذ عملية قراءة في قاعدة البيانات الخاصة بك، هذا يعني أنّه سيتم تحصيل رسوم منك مقابل قراءة المستندات حتى إذا رفضت قواعدك الطلب. الاطّلاع على أسعار "Cloud Firestore" للحصول على معلومات فوترة أكثر تحديدًا.

الدوال المخصصة

نظرًا لأن قواعد الأمان أصبحت أكثر تعقيدًا، فقد تحتاج إلى التفاف مجموعات الشروط في الدوال التي يمكنك إعادة استخدامها عبر مجموعة القواعد. قواعد الأمان تتيح الدوال المخصصة. يشبه أسلوب كتابة الدوالّ المخصّصة إلى حدٍّ ما أسلوب كتابة JavaScript، ولكنّ دوالّ قواعد الأمان مكتوبة بلغة خاصة بالمجال تفرض بعض القيود المهمة:

  • يمكن أن تحتوي الدوالّ على عبارة return واحدة فقط. لا يمكنهم تحتوي على أي منطق إضافي. على سبيل المثال، لا يمكنها تنفيذ التكرارات الحلقية أو استدعاء والخدمات الخارجية.
  • يمكن للدوالّ الوصول تلقائيًا إلى الدوالّ والمتغيّرات من النطاق الذي تم تعريفها فيه. على سبيل المثال، الدالة المحددة داخل بإمكان النطاق service cloud.firestore الوصول إلى المتغيّر resource. والدوال المدمَجة مثل get() وexists()
  • قد تستدعي الدوال دوال أخرى ولكنها قد لا تتكرر. يقتصر إجمالي عمق تسلسل استدعاء الدوال البرمجية على 10.
  • في إصدار القواعد v2، يمكن أن تحدِّد الدوال المتغيّرات باستخدام الكلمة الرئيسية let. يمكن أن تحتوي الدوال على ما يصل إلى 10 روابط السماح، ولكن يجب أن تنتهي بإرجاع. الشخصي.

يتم تحديد الدالة باستخدام الكلمة الرئيسية 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:

محتوى مخصّص للويب
db.collection("cities").get()
    .then(function(querySnapshot) {
        querySnapshot.forEach(function(doc) {
            console.log(doc.id, " => ", doc.data());
    });
});

مسموح به: تسمح هذه القاعدة بطلب البحث التالي لأنّ العبارة where("visibility", "==", "public") تضمن أن مجموعة النتائج تستوفي شرط القاعدة:

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

تقيِّم قواعد أمان Cloud Firestore كل طلب بحث استنادًا إلى نتيجة محتملة، وترفض الطلب إذا كان من المحتمل أن يعرض مستندًا ليس لبرنامج العميل إذن بقراءته. يجب أن تتبع طلبات البحث القيود التي تم ضبطها بواسطة قواعد الأمان الخاصة بك. لمزيد من المعلومات حول قواعد الأمان وطلبات البحث، راجع قسم والاستعلام عن البيانات.

الخطوات التالية