قواعد الأمان الأساسية

تتيح لك Firebase Security Rules التحكّم في الوصول إلى بياناتك المخزّنة. تعني بنية قواعد المرنة أنّه يمكنك إنشاء قواعد تتطابق مع أي شيء، بدءًا من جميع عمليات الكتابة في قاعدة البيانات بالكامل إلى العمليات التي يتم إجراؤها على مستند معيّن.

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

للوصول إلى القواعد وتعديلها، اتّبِع الخطوات الموضّحة في مقالة إدارة Firebase Security Rules ونشره.

القواعد التلقائية: وضع القفل

عند إنشاء مثيل قاعدة بيانات أو مساحة تخزين في وحدة تحكّم Firebase، يمكنك اختيار ما إذا كان Firebase Security Rules سيحظر الوصول إلى بياناتك (الوضع المُقفَل) أو سيسمح لأي مستخدم بالوصول إليها (الوضع التجريبي). في Cloud Firestore و Realtime Database، تمنع القواعد التلقائية للوضع المُقفَل الوصول إلى جميع المستخدمين. في Cloud Storage، يمكن فقط للمستخدمين الذين تم إثبات هويتهم الوصول إلى حِزم التخزين.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if false;
    }
  }
}

Realtime Database

{
  "rules": {
    ".read": false,
    ".write": false
  }
}

Cloud Storage

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth != null;
    }
  }
}

قواعد بيئة التطوير

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

تذكَّر أنّ Firebase تسمح للعملاء بالوصول المباشر إلى بياناتك، وتعدّ Firebase Security Rules هي الإجراء الوقائي الوحيد الذي يحظر وصول المستخدمين الضارّين. إنّ تحديد القواعد بشكل منفصل عن منطق المنتج له عدد من المزايا: لا يتحمّل العملاء مسؤولية فرض الأمان، ولن تؤدي عمليات التنفيذ التي تتضمّن أخطاء إلى تعريض بياناتك للخطر، والأهم من ذلك، أنّك لا تعتمد على خادم وسيط لحماية البيانات من العالم.

جميع المستخدمين الذين تمّت مصادقتهم

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

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth != null;
    }
  }
}

Realtime Database

{
  "rules": {
    ".read": "auth.uid !== null",
    ".write": "auth.uid !== null"
  }
}

Cloud Storage

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth != null;
    }
  }
}

القواعد الجاهزة للنشر

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

ننصحك بكتابة القواعد أثناء تنظيم بياناتك، لأنّ طريقة إعداد قواعدك تؤثّر في كيفية تقييد الوصول إلى البيانات في مسارات مختلفة.

إذن وصول لمالك المحتوى فقط

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

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

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

لإعداد هذه القاعدة: أنشئ قاعدة تؤكّد أنّ المستخدم الذي يطلب الوصول لقراءة البيانات أو كتابتها هو المستخدم الذي يملك هذه البيانات.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow only authenticated content owners access
    match /some_collection/{userId}/{documents=**} {
      allow read, write: if request.auth != null && request.auth.uid == userId
    }
  }
}

Realtime Database

{
  "rules": {
    "some_path": {
      "$uid": {
        // Allow only authenticated content owners access to their data
        ".read": "auth !== null && auth.uid === $uid",
        ".write": "auth !== null && auth.uid === $uid"
      }
    }
  }
}

Cloud Storage

// Grants a user access to a node matching their user ID
service firebase.storage {
  match /b/{bucket}/o {
    // Files look like: "user/<UID>/path/to/file.txt"
    match /user/{userId}/{allPaths=**} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
    }
  }
}

أذونات وصول مختلطة عامة وخاصة

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

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

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

لإعداد هذه القاعدة: أنشئ قاعدة تتيح إذن الوصول للقراءة لجميع المستخدمين (أو جميع المستخدمين الذين تمّت مصادقة هويتهم)، وتؤكّد أنّ المستخدم الذي يكتب البيانات هو المالك.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow public read access, but only content owners can write
    match /some_collection/{document} {
      // Allow public reads
      allow read: if true
      // Allow creation if the current user owns the new document
      allow create: if request.auth.uid == request.resource.data.author_uid;
      // Allow updates by the owner, and prevent change of ownership
      allow update: if request.auth.uid == request.resource.data.author_uid
                    && request.auth.uid == resource.data.author_uid;
      // Allow deletion if the current user owns the existing document
      allow delete: if request.auth.uid == resource.data.author_uid;
    }
  }
}

Realtime Database

{
// Allow anyone to read data, but only authenticated content owners can
// make changes to their data

  "rules": {
    "some_path": {
      "$uid": {
        ".read": true,
        // or ".read": "auth.uid !== null" for only authenticated users
        ".write": "auth.uid === $uid"
      }
    }
  }
}

Cloud Storage

service firebase.storage {
  match /b/{bucket}/o {
    // Files look like: "user/<UID>/path/to/file.txt"
    match /user/{userId}/{allPaths=**} {
      allow read;
      allow write: if request.auth.uid == userId;
    }
  }
}

الوصول المستنِد إلى السمات والوصول المستنِد إلى الدور

لكي تعمل هذه القواعد، عليك تحديد سمات للمستخدمين في بياناتك وتحديدها لهم. Firebase Security Rules التحقّق من الطلب مقارنةً بالبيانات الواردة من قاعدة البيانات أو metadata الملف لتأكيد الوصول أو رفضه

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

حالات عدم عمل هذه القاعدة: في Realtime Database وCloud Storage، لا يمكن لقواعدك الاستفادة من طريقة get() التي يمكن أن تدمجها قواعد Cloud Firestore. ونتيجةً لذلك، عليك تنظيم البيانات الوصفية لقاعدة بياناتك أو ملفك لتعكس السمات التي تستخدمها في قواعدك.

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

يمكنك أيضًا إعداد مطالبات مخصّصة في Authentication ثم استرداد هذه المعلومات من المتغيّر auth.token في أيّ Firebase Security Rules.

السمات والأدوار المحدّدة بالبيانات

لا تعمل هذه القواعد إلا في Cloud Firestore وRealtime Database.

Cloud Firestore

تذكَّر أنّه في أي وقت تتضمّن فيه قواعدك عملية قراءة، مثل القواعد أدناه، يتم تحصيل رسوم منك مقابل عملية قراءة في Cloud Firestore.

service cloud.firestore {
  match /databases/{database}/documents {
    // For attribute-based access control, Check a boolean `admin` attribute
    allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true;
    allow read: true;

    // Alterntatively, for role-based access, assign specific roles to users
    match /some_collection/{document} {
     allow read: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "Reader"
     allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "Writer"
   }
  }
}

Realtime Database

{
  "rules": {
    "some_path": {
      "${subpath}": {
        //
        ".write": "root.child('users').child(auth.uid).child('role').val() === 'admin'",
        ".read": true
      }
    }
  }
}

سمات المطالبات المخصّصة والأدوار

لتنفيذ هذه القواعد، عليك إعداد مطالبات مخصّصة في Firebase Authentication ثم الاستفادة من المطالبات في قواعدك.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    // For attribute-based access control, check for an admin claim
    allow write: if request.auth.token.admin == true;
    allow read: true;

    // Alterntatively, for role-based access, assign specific roles to users
    match /some_collection/{document} {
     allow read: if request.auth.token.reader == "true";
     allow write: if request.auth.token.writer == "true";
   }
  }
}

Realtime Database

{
  "rules": {
    "some_path": {
      "$uid": {
        // Create a custom claim for each role or group
        // you want to leverage
        ".write": "auth.uid !== null && auth.token.writer === true",
        ".read": "auth.uid !== null && auth.token.reader === true"
      }
    }
  }
}

Cloud Storage

service firebase.storage {
  // 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;
  }
}

سمات المستأجر

لتنفيذ هذه القواعد، عليك إعداد ميزة استئجار مساحات متعددة في Google Cloud Identity Platform ‏ (GCIP)، ثم الاستفادة من المستأجر في قواعدك. تسمح الأمثلة التالية بالكتابة من مستخدم في مستأجر معيّن، مثل tenant2-m6tyz.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    // For tenant-based access control, check for a tenantID
    allow write: if request.auth.token.firebase.tenant == 'tenant2-m6tyz';
    allow read: true;
  }
}

Realtime Database

{
  "rules": {
    "some_path": {
      "$uid": {
        // Only allow reads and writes if user belongs to a specific tenant
        ".write": "auth.uid !== null && auth.token.firebase.tenant === 'tenant2-m6tyz'",
        ".read": "auth.uid !== null
      }
    }
  }
}

Cloud Storage

service firebase.storage {
  // Only allow reads and writes if user belongs to a specific tenant
  match /files/{tenantId}/{fileName} {
    allow read: if request.auth != null;
    allow write: if request.auth.token.firebase.tenant == tenantId;
  }
}