استخدام الشروط في قواعد أمان 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) بالإضافة إلى مطالبات Firebase Authentication JWT (request.auth.token).

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

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

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

  • محتوى متاح للجميع: تجاهُل request.auth
  • Authenticated private: check that request.auth is not null
  • User private: check that request.auth.uid equals a path 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 يحتوي على معلومات إضافية عن عضو في المجموعة (مثل معرّف المجموعة)
  • تضمين معلومات المجموعة (مثل معرّف المجموعة أو قائمة 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 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 تفعيل الأذونات لربط المنتجَين.

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

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

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

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