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

يستند هذا الدليل إلى دليل التعرّف على بنية Firebase Security Rules الأساسية لتوضيح كيفية إضافة شروط إلى Firebase Security Rules من أجل Cloud Storage.

الوحدة الأساسية لـ Cloud Storage Security Rules هي الشرط. الشرط هو تعبير منطقي يحدّد ما إذا كان يجب السماح بعملية معيّنة أو رفضها. بالنسبة إلى القواعد الأساسية، يكون استخدام القيم الحرفية true وfalse كشروط مناسبًا تمامًا. لكنّ Firebase Security Rules للغة Cloud Storage توفّر لك طرقًا لكتابة شروط أكثر تعقيدًا يمكنها:

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

للحصول على مساعدة من الذكاء الاصطناعي، انسخ الطلب أدناه إلى وكيل الترميز المستند إلى الذكاء الاصطناعي (مثل "Gemini في استوديو Android" وAntigravity وClaude Code وCodex وCursor). يمكنك تخصيص الطلب وتكراره مع الوكيل. يمكنك الانتقال إلى مهارات وكلاء Firebase للحصول على معلومات مفصّلة حول التثبيت.

Help me use Firebase in my app.
1. Make sure that **Firebase agent skills** are installed and updated. For Claude Code, Codex, or Cursor agents, help me install the Firebase plugin. For other agents, run `npx skills add firebase/agent-skills`. Always try to use **Firebase agent skills** for Firebase-related tasks.
2. Help me write, validate, and deploy Firebase Security Rules to protect my app's Cloud Storage data.

المصادقة

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

عندما يرسل مستخدم مصادَق عليه طلبًا إلى Cloud Storage، يتم ملء المتغيّر request.auth بمعلومات uid الخاصة بالمستخدم (request.auth.uid) بالإضافة إلى مطالبات رمز JWT المميز Firebase Authentication (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 Authentication رمز مميّز مخصّص يتضمّن معلومات إضافية عن أحد أعضاء المجموعة (مثل معرّف المجموعة)
  • تضمين معلومات المجموعة (مثل معرّف المجموعة أو قائمة uids المصرّح بها) في بيانات الملف الوصفية

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

// 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 Authentication في عنصر request.auth كما هو موضّح أعلاه، يحتوي المتغيّر request على مسار الملف الذي يتم فيه تنفيذ الطلب، والوقت الذي تم فيه تلقّي الطلب، وقيمة resource الجديدة إذا كان الطلب عبارة عن عملية كتابة.

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

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

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

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

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

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

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

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

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

تحتوي 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)).data.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 Security Rules الأول وحفظه باستخدام وظائف Cloud Firestore، سيُطلب منك في وحدة تحكّم Firebase أو واجهة سطر الأوامر Firebase تفعيل الأذونات لربط المنتجين.

يمكنك إيقاف الميزة من خلال إزالة دور إدارة الهوية وإمكانية الوصول (IAM)، كما هو موضّح في إدارة Firebase Security Rules ونشره.

التأكُّد من صحة البيانات

يمكن استخدام Firebase Security Rules لـ Cloud Storage أيضًا للتحقّق من صحة البيانات، بما في ذلك التحقّق من صحة اسم الملف ومساره وخصائص البيانات الوصفية للملف، مثل 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 Security Rules أكثر تعقيدًا، قد تحتاج إلى تضمين مجموعات من الشروط في دوال يمكنك إعادة استخدامها في مجموعة القواعد. تتيح قواعد الأمان استخدام دوال مخصّصة. يشبه بناء جملة الدوال المخصّصة إلى حد ما بناء جملة JavaScript، ولكن تتم كتابة دوال Firebase Security Rules بلغة خاصة بالمجال تتضمّن بعض القيود المهمة:

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

يتم تعريف الدالة باستخدام الكلمة الأساسية 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 Security Rules إلى تسهيل صيانتها مع زيادة تعقيد قواعدك.

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

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

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