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

تتيح لك 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 read: if true
      allow create: if request.auth.uid == request.resource.data.author_uid;
      allow update, 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" بالاستناد إلى البيانات من قاعدة بياناتك أو ملفك. البيانات الوصفية لتأكيد الوصول أو رفضه.

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

حالات عدم عمل هذه القاعدة: في 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;
  }
}