استخدم الشروط في قواعد أمان Firebase Cloud Storage

يعتمد هذا الدليل على تعلم البنية الأساسية لدليل اللغة لقواعد أمان Firebase لإظهار كيفية إضافة شروط إلى قواعد أمان Firebase للتخزين السحابي.

العنصر الأساسي لقواعد أمان التخزين السحابي هو الشرط . الشرط هو تعبير منطقي يحدد ما إذا كان يجب السماح بعملية معينة أم رفضها. بالنسبة للقواعد الأساسية، فإن استخدام القيم الحرفية true false كشروط يعمل بشكل جيد تمامًا. لكن قواعد أمان Firebase للغة التخزين السحابي تمنحك طرقًا لكتابة شروط أكثر تعقيدًا يمكنها:

  • التحقق من مصادقة المستخدم
  • التحقق من صحة البيانات الواردة

المصادقة

تتكامل قواعد أمان Firebase للتخزين السحابي مع مصادقة Firebase لتوفير مصادقة قوية تعتمد على المستخدم للتخزين السحابي. يسمح هذا بالتحكم الدقيق في الوصول استنادًا إلى مطالبات رمز Firebase Authentication المميز.

عندما يقوم مستخدم تمت مصادقته بتنفيذ طلب مقابل Cloud Storage، يتم ملء متغير request.auth بالمعرف uid الخاص بالمستخدم ( request.auth.uid ) بالإضافة إلى مطالبات Firebase Authentication JWT ( request.auth.token ).

بالإضافة إلى ذلك، عند استخدام المصادقة المخصصة، تظهر مطالبات إضافية في حقل request.auth.token .

عندما يقوم مستخدم غير مصادق بتنفيذ طلب، يكون المتغير request.auth null .

باستخدام هذه البيانات، هناك عدة طرق شائعة لاستخدام المصادقة لتأمين الملفات:

  • عام: تجاهل request.auth
  • تمت المصادقة عليه بشكل خاص: تأكد من أن request.auth ليس null
  • خاص بالمستخدم: تأكد من أن request.auth.uid يساوي uid المسار
  • مجموعة خاصة: تحقق من مطالبات الرمز المميز المخصص لمطابقة المطالبة المختارة، أو اقرأ البيانات التعريفية للملف لمعرفة ما إذا كان هناك حقل بيانات التعريف موجودًا

عام

يمكن اعتبار أي قاعدة لا تأخذ في الاعتبار سياق request.auth قاعدة public ، لأنها لا تأخذ في الاعتبار سياق المصادقة الخاص بالمستخدم. يمكن أن تكون هذه القواعد مفيدة لعرض البيانات العامة مثل أصول اللعبة أو ملفات الصوت أو أي محتوى ثابت آخر.

// Anyone to read a public image if the file is less than 100kB
// Anyone can upload a public file ending in '.txt'
match /public/{imageId} {
  allow read: if resource.size < 100 * 1024;
  allow write: if imageId.matches(".*\\.txt");
}

خاصة موثقة

في بعض الحالات، قد ترغب في أن تكون البيانات قابلة للعرض بواسطة جميع المستخدمين المصادق عليهم لتطبيقك، ولكن ليس بواسطة المستخدمين غير المصادقين. نظرًا لأن المتغير request.auth null لجميع المستخدمين غير المصادقين، فكل ما عليك فعله هو التحقق من وجود المتغير request.auth حتى تتمكن من طلب المصادقة:

// Require authentication on all internal image reads
match /internal/{imageId} {
  allow read: if request.auth != null;
}

المستخدم خاص

إلى حد بعيد، ستكون حالة الاستخدام الأكثر شيوعًا لـ request.auth هي تزويد المستخدمين الفرديين بأذونات دقيقة على ملفاتهم: بدءًا من تحميل صور الملفات الشخصية وحتى قراءة المستندات الخاصة.

نظرًا لأن الملفات الموجودة في Cloud Storage لها "مسار" كامل للملف، فإن كل ما يتطلبه الأمر لإنشاء ملف يتحكم فيه المستخدم هو جزء من معلومات تعريف المستخدم الفريدة في بادئة اسم الملف (مثل uid الخاص بالمستخدم ) والتي يمكن التحقق منها عندما يتم تقييم القاعدة:

// Only a user can upload their profile picture, but anyone can view it
match /users/{userId}/profilePicture.png {
  allow read;
  allow write: if request.auth.uid == userId;
}

المجموعة خاصة

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

بمجرد تخزين هذه البيانات في الرمز المميز أو البيانات التعريفية للملف، يمكن الرجوع إليها من داخل القاعدة:

// Allow reads if the group ID in your token matches the file metadata's `owner` property
// Allow writes if the group ID is in the user's custom token
match /files/{groupId}/{fileName} {
  allow read: if resource.metadata.owner == request.auth.token.groupId;
  allow write: if request.auth.token.groupId == groupId;
}

طلب التقييم

يتم تقييم عمليات التحميل والتنزيلات وتغييرات البيانات التعريفية والحذف باستخدام request المرسل إلى Cloud Storage. بالإضافة إلى المعرف الفريد للمستخدم وحمولة مصادقة Firebase في كائن request.auth كما هو موضح أعلاه، يحتوي متغير request على مسار الملف حيث يتم تنفيذ الطلب، والوقت الذي تم فيه تلقي الطلب، وقيمة resource الجديدة إذا الطلب هو الكتابة.

يحتوي كائن request أيضًا على المعرف الفريد للمستخدم وحمولة مصادقة Firebase في كائن request.auth ، والذي سيتم شرحه بشكل أكبر في قسم الأمان المستند إلى المستخدم في المستندات.

تتوفر قائمة كاملة بالخصائص الموجودة في كائن request أدناه:

ملكية يكتب وصف
auth خريطة <سلسلة، سلسلة> عندما يقوم مستخدم بتسجيل الدخول، يتم توفير uid والمعرف الفريد للمستخدم والرمز المميز token لمطالبات Firebase Authentication JWT. وإلا فإنه سيكون null .
params خريطة <سلسلة، سلسلة> خريطة تحتوي على معلمات الاستعلام الخاصة بالطلب.
path طريق path يمثل المسار الذي يتم تنفيذ الطلب فيه.
resource خريطة <سلسلة، سلسلة> قيمة المورد الجديدة، موجودة فقط في طلبات write .
time الطابع الزمني طابع زمني يمثل وقت الخادم الذي يتم فيه تقييم الطلب.

تقييم الموارد

عند تقييم القواعد، قد ترغب أيضًا في تقييم البيانات التعريفية للملف الذي يتم تحميله أو تنزيله أو تعديله أو حذفه. يتيح لك ذلك إنشاء قواعد معقدة وقوية تقوم بأشياء مثل السماح فقط بتحميل الملفات التي تحتوي على أنواع معينة من المحتوى، أو حذف الملفات التي يزيد حجمها عن حجم معين فقط.

توفر قواعد أمان Firebase للتخزين السحابي بيانات تعريف الملف في كائن resource ، والذي يحتوي على أزواج المفاتيح/القيمة للبيانات التعريفية التي تظهر في كائن التخزين السحابي. يمكن فحص هذه الخصائص عند طلبات read أو write لضمان سلامة البيانات.

في طلبات write (مثل التحميلات وتحديثات بيانات التعريف والحذف)، بالإضافة إلى كائن resource ، الذي يحتوي على بيانات تعريف الملف للملف الموجود حاليًا في مسار الطلب، لديك أيضًا القدرة على استخدام كائن request.resource ، الذي يحتوي على مجموعة فرعية من البيانات التعريفية للملف المراد كتابتها إذا سمح بالكتابة. يمكنك استخدام هاتين القيمتين لضمان تكامل البيانات أو فرض قيود التطبيق مثل نوع الملف أو حجمه.

تتوفر قائمة كاملة بالخصائص الموجودة في كائن resource أدناه:

ملكية يكتب وصف
name خيط الاسم الكامل للكائن
bucket خيط اسم الدلو الذي يوجد فيه هذا الكائن.
generation كثافة العمليات إنشاء كائن Google Cloud Storage لهذا الكائن.
metageneration كثافة العمليات إنشاء كائن Google Cloud Storage لهذا الكائن.
size كثافة العمليات حجم الكائن بالبايت.
timeCreated الطابع الزمني طابع زمني يمثل الوقت الذي تم فيه إنشاء الكائن.
updated الطابع الزمني طابع زمني يمثل الوقت الذي تم فيه آخر تحديث للكائن.
md5Hash خيط تجزئة MD5 للكائن.
crc32c خيط تجزئة crc32c للكائن.
etag خيط العلامة المرتبطة بهذا الكائن.
contentDisposition خيط التصرف في المحتوى المرتبط بهذا الكائن.
contentEncoding خيط ترميز المحتوى المرتبط بهذا الكائن.
contentLanguage خيط لغة المحتوى المرتبطة بهذا الكائن.
contentType خيط نوع المحتوى المرتبط بهذا الكائن.
metadata خريطة <سلسلة، سلسلة> أزواج المفاتيح/القيمات من البيانات التعريفية المخصصة الإضافية التي حددها المطور.

يحتوي request.resource على كل هذه العناصر باستثناء generation metageneration و etag و timeCreated updated .

تعزيز مع Cloud Firestore

يمكنك الوصول إلى المستندات في Cloud Firestore لتقييم معايير الترخيص الأخرى.

باستخدام وظائف firestore.get() و firestore.exists() ، يمكن لقواعد الأمان الخاصة بك تقييم الطلبات الواردة مقابل المستندات الموجودة في Cloud Firestore. تتوقع الدالتان firestore.get() و firestore.exists() مسارات وثيقة محددة بالكامل. عند استخدام المتغيرات لإنشاء مسارات لـ firestore.get() و firestore.exists() ، فإنك تحتاج إلى الهروب من المتغيرات بشكل صريح باستخدام بناء الجملة $(variable) .

في المثال أدناه، نرى قاعدة تقيد الوصول للقراءة إلى الملفات على المستخدمين الذين هم أعضاء في أندية معينة.

service firebase.storage {
  match /b/{bucket}/o {
    match /users/{club}/files/{fileId} {
      allow read: if club in
        firestore.get(/databases/(default)/documents/users/$(request.auth.id)).memberships
    }
  }
}
في المثال التالي، يمكن لأصدقاء المستخدم فقط رؤية صورهم.
service firebase.storage {
  match /b/{bucket}/o {
    match /users/{userId}/photos/{fileId} {
      allow read: if
        firestore.exists(/databases/(default)/documents/users/$(userId)/friends/$(request.auth.id))
    }
  }
}

بمجرد إنشاء وحفظ أول قواعد أمان Cloud Storage التي تستخدم وظائف Cloud Firestore هذه، ستتم مطالبتك في وحدة تحكم Firebase أو Firebase CLI لتمكين الأذونات لتوصيل المنتجين.

يمكنك تعطيل الميزة عن طريق إزالة دور IAM، كما هو موضح في إدارة ونشر قواعد أمان Firebase .

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

يمكن أيضًا استخدام قواعد أمان Firebase للتخزين السحابي للتحقق من صحة البيانات، بما في ذلك التحقق من صحة اسم الملف ومساره بالإضافة إلى خصائص بيانات تعريف الملف مثل contentType و size .

service firebase.storage {
  match /b/{bucket}/o {
    match /images/{imageId} {
      // Only allow uploads of any image file that's less than 5MB
      allow write: if request.resource.size < 5 * 1024 * 1024
                   && request.resource.contentType.matches('image/.*');
    }
  }
}

وظائف مخصصة

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

  • يمكن أن تحتوي الوظائف على عبارة return واحدة فقط. ولا يمكن أن تحتوي على أي منطق إضافي. على سبيل المثال، لا يمكنهم تنفيذ الحلقات أو الاتصال بخدمات خارجية.
  • يمكن للوظائف الوصول تلقائيًا إلى الوظائف والمتغيرات من النطاق الذي تم تعريفها فيه. على سبيل المثال، تتمتع الوظيفة المحددة ضمن نطاق service firebase.storage بإمكانية الوصول إلى متغير resource ، وبالنسبة لـ Cloud Firestore فقط، تتمتع الوظائف المضمنة مثل get() و exists() .
  • قد تستدعي الوظائف وظائف أخرى ولكن لا يجوز تكرارها. يقتصر إجمالي عمق مكدس الاستدعاءات على 10.
  • في الإصدار rules2 ، يمكن للوظائف تحديد المتغيرات باستخدام الكلمة الأساسية let . يمكن أن تحتوي الوظائف على أي عدد من روابط Let، لكن يجب أن تنتهي ببيان return.

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

service firebase.storage {
  match /b/{bucket}/o {
    // 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 /images/{imageId} {
      allow read, write: if signedInOrPublic();
    }
    match /mp3s/{mp3Ids} {
      allow read: if signedInOrPublic();
    }
  }
}

إن استخدام الوظائف في قواعد أمان Firebase الخاصة بك يجعلها أكثر قابلية للصيانة مع تزايد تعقيد قواعدك.

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

بعد هذه المناقشة للشروط، سيكون لديك فهم أكثر تعقيدًا للقواعد وستكون جاهزًا للقيام بما يلي:

تعرف على كيفية التعامل مع حالات الاستخدام الأساسية، وتعرف على سير العمل لتطوير القواعد واختبارها ونشرها: