يعتمد هذا الدليل على تعلم البنية الأساسية لدليل اللغة لقواعد أمان 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; }
المجموعة خاصة
هناك حالة استخدام أخرى شائعة بنفس القدر وهي السماح بأذونات المجموعة على كائن، مثل السماح للعديد من أعضاء الفريق بالتعاون في مستند مشترك. هناك عدة طرق للقيام بذلك:
- سك رمزًا مميزًا مخصصًا لمصادقة Firebase يحتوي على معلومات إضافية حول عضو المجموعة (مثل معرف المجموعة)
- قم بتضمين معلومات المجموعة (مثل معرف المجموعة أو قائمة
uid
المعتمدة) في البيانات التعريفية للملف
بمجرد تخزين هذه البيانات في الرمز المميز أو البيانات التعريفية للملف، يمكن الرجوع إليها من داخل القاعدة:
// 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 الخاصة بك يجعلها أكثر قابلية للصيانة مع تزايد تعقيد قواعدك.
الخطوات التالية
بعد هذه المناقشة للشروط، سيكون لديك فهم أكثر تعقيدًا للقواعد وستكون جاهزًا للقيام بما يلي:
تعرف على كيفية التعامل مع حالات الاستخدام الأساسية، وتعرف على سير العمل لتطوير القواعد واختبارها ونشرها:
- اكتب القواعد التي تتناول السيناريوهات الشائعة .
- اعتمد على معرفتك من خلال مراجعة المواقف التي يجب عليك فيها اكتشاف القواعد غير الآمنة وتجنبها .
- اختبار القواعد باستخدام محاكي Cloud Storage ومكتبة اختبار قواعد الأمان المخصصة .
- قم بمراجعة الطرق المتاحة لنشر القواعد .