التحقّق من صحة البيانات

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

اختَر منتجًا في كل قسم لمعرفة المزيد عن قواعد التحقّق من صحة البيانات.

للحصول على مساعدة من الذكاء الاصطناعي، انسخ الطلب أدناه إلى وكيل الترميز بالذكاء الاصطناعي (مثل 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 data.

القيود المفروضة على البيانات الجديدة

Cloud Firestore

إذا أردت التأكّد من عدم إنشاء مستند يحتوي على حقل معيّن، يمكنك تضمين الحقل في الشرط allow. على سبيل المثال، إذا أردت رفض إنشاء أي مستندات تحتوي على الحقل ranking، يمكنك حظر ذلك في الشرط create.

  service cloud.firestore {
    match /databases/{database}/documents {
      // Disallow
      match /cities/{city} {
        allow create: if !("ranking" in request.resource.data)
      }
    }
  }

Realtime Database

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

  {
    "rules": {
      // Write is allowed for all paths
      ".write": true,
      // Allows writes only if new data doesn't include a `ranking` child value
      ".validate": "!newData.hasChild('ranking')
    }
  }

Cloud Storage

إذا أردت التأكّد من عدم إنشاء ملف يحتوي على بيانات وصفية معيّنة، يمكنك تضمين البيانات الوصفية في الشرط allow. على سبيل المثال، إذا أردت رفض إنشاء أي ملفات تحتوي على بيانات ranking الوصفية، يمكنك حظرها في الشرط create.

  service firebase.storage {
    match /b/{bucket}/o {
      match /files/{fileName} {
      // Disallow
        allow create: if !("ranking" in request.resource.metadata)
      }
    }
  }

استخدام البيانات الحالية في Firebase Security Rules

Cloud Firestore

تخزّن العديد من التطبيقات معلومات التحكّم في الوصول كحقول في المستندات في قاعدة البيانات. يمكن لـ "Cloud Firestore Security Rules" السماح بالوصول أو رفضه ديناميكيًا استنادًا إلى بيانات المستند:

  service cloud.firestore {
    match /databases/{database}/documents {
      // Allow the user to read data if the document has the 'visibility'
      // field set to 'public'
      match /cities/{city} {
        allow read: if resource.data.visibility == 'public';
      }
    }
  }

يشير المتغيّر resource إلى المستند المطلوب، بينما يمثّل resource.data خريطة لجميع الحقول والقيم المخزّنة في المستند. لمزيد من المعلومات حول المتغيّر resource، يُرجى الاطّلاع على المستندات المرجعية.

عند كتابة البيانات، قد تحتاج إلى مقارنة البيانات الواردة بالبيانات الحالية. يتيح لك ذلك تنفيذ إجراءات مثل التأكّد من عدم تغيير حقل معيّن أو من زيادة قيمة حقل معيّن بمقدار واحد فقط أو من أنّ القيمة الجديدة ستكون بعد أسبوع على الأقل في المستقبل. في هذه الحالة، إذا كانت مجموعة القواعد تسمح بالكتابة المعلّقة، يحتوي المتغيّر request.resource على الحالة المستقبلية للمستند. بالنسبة إلى عمليات update التي تعدّل فقط مجموعة فرعية من حقول المستند، سيحتوي المتغيّر request.resource على حالة المستند المعلّقة بعد العملية. يمكنك التحقّق من قيم الحقول في request.resource لمنع تعديلات البيانات غير المرغوب فيها أو غير المتّسقة:

   service cloud.firestore {
     match /databases/{database}/documents {
      // Make sure all cities have a positive population and
      // the name is not changed
      match /cities/{city} {
        allow update: if request.resource.data.population > 0
                      && request.resource.data.name == resource.data.name;
      }
    }
  }

Realtime Database

في Realtime Database، استخدِم قواعد .validate لفرض هياكل البيانات والتحقّق من صحة تنسيق البيانات ومحتواها. يتم تشغيل قواعد Security Rules .validate بعد التحقّق من أنّ قاعدة .write تمنح إذن الوصول.

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

ضَع في اعتبارك قواعد .validate التالية:

  {
    "rules": {
      // write is allowed for all paths
      ".write": true,
      "widget": {
        // a valid widget must have attributes "color" and "size"
        // allows deleting widgets (since .validate is not applied to delete rules)
        ".validate": "newData.hasChildren(['color', 'size'])",
        "size": {
          // the value of "size" must be a number between 0 and 99
          ".validate": "newData.isNumber() &&
                        newData.val() >= 0 &&
                        newData.val() <= 99"
        },
        "color": {
          // the value of "color" must exist as a key in our mythical
          // /valid_colors/ index
          ".validate": "root.child('valid_colors/' + newData.val()).exists()"
        }
      }
    }
  }

تؤدي طلبات الكتابة إلى قاعدة بيانات تتضمّن القواعد السابقة إلى النتائج التالية:

JavaScript
var ref = db.ref("/widget");

// PERMISSION_DENIED: does not have children color and size
ref.set('foo');

// PERMISSION DENIED: does not have child color
ref.set({size: 22});

// PERMISSION_DENIED: size is not a number
ref.set({ size: 'foo', color: 'red' });

// SUCCESS (assuming 'blue' appears in our colors list)
ref.set({ size: 21, color: 'blue'});

// If the record already exists and has a color, this will
// succeed, otherwise it will fail since newData.hasChildren(['color', 'size'])
// will fail to validate
ref.child('size').set(99);
Objective-C
ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
FIRDatabaseReference *ref = [[[FIRDatabase database] reference] child: @"widget"];

// PERMISSION_DENIED: does not have children color and size
[ref setValue: @"foo"];

// PERMISSION DENIED: does not have child color
[ref setValue: @{ @"size": @"foo" }];

// PERMISSION_DENIED: size is not a number
[ref setValue: @{ @"size": @"foo", @"color": @"red" }];

// SUCCESS (assuming 'blue' appears in our colors list)
[ref setValue: @{ @"size": @21, @"color": @"blue" }];

// If the record already exists and has a color, this will
// succeed, otherwise it will fail since newData.hasChildren(['color', 'size'])
// will fail to validate
[[ref child:@"size"] setValue: @99];
Swift
ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
var ref = FIRDatabase.database().reference().child("widget")

// PERMISSION_DENIED: does not have children color and size
ref.setValue("foo")

// PERMISSION DENIED: does not have child color
ref.setValue(["size": "foo"])

// PERMISSION_DENIED: size is not a number
ref.setValue(["size": "foo", "color": "red"])

// SUCCESS (assuming 'blue' appears in our colors list)
ref.setValue(["size": 21, "color": "blue"])

// If the record already exists and has a color, this will
// succeed, otherwise it will fail since newData.hasChildren(['color', 'size'])
// will fail to validate
ref.child("size").setValue(99);
Java
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("widget");

// PERMISSION_DENIED: does not have children color and size
ref.setValue("foo");

// PERMISSION DENIED: does not have child color
ref.child("size").setValue(22);

// PERMISSION_DENIED: size is not a number
Map<String,Object> map = new HashMap<String, Object>();
map.put("size","foo");
map.put("color","red");
ref.setValue(map);

// SUCCESS (assuming 'blue' appears in our colors list)
map = new HashMap<String, Object>();
map.put("size", 21);
map.put("color","blue");
ref.setValue(map);

// If the record already exists and has a color, this will
// succeed, otherwise it will fail since newData.hasChildren(['color', 'size'])
// will fail to validate
ref.child("size").setValue(99);
REST
# PERMISSION_DENIED: does not have children color and size
curl -X PUT -d 'foo' \
https://docs-examples.firebaseio.com/rest/securing-data/example.json

# PERMISSION DENIED: does not have child color
curl -X PUT -d '{"size": 22}' \
https://docs-examples.firebaseio.com/rest/securing-data/example.json

# PERMISSION_DENIED: size is not a number
curl -X PUT -d '{"size": "foo", "color": "red"}' \
https://docs-examples.firebaseio.com/rest/securing-data/example.json

# SUCCESS (assuming 'blue' appears in our colors list)
curl -X PUT -d '{"size": 21, "color": "blue"}' \
https://docs-examples.firebaseio.com/rest/securing-data/example.json

# If the record already exists and has a color, this will
# succeed, otherwise it will fail since newData.hasChildren(['color', 'size'])
# will fail to validate
curl -X PUT -d '99' \
https://docs-examples.firebaseio.com/rest/securing-data/example/size.json

Cloud Storage

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

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

  service firebase.storage {
    match /b/{bucket}/o {
      match /images {
        match /{fileName} {
          // Allow reads if a custom 'visibility' field is set to 'public'
          allow read: if resource.metadata.visibility == 'public';
        }
      }
    }
  }

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

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

  service firebase.storage {
    match /b/{bucket}/o {
      match /images {
        // Allow write files to the path "images/*", subject to the constraints:
        // 1) File is less than 5MB
        // 2) Content type is an image
        // 3) Uploaded content type matches existing content type
        // 4) Filename (stored in imageId wildcard variable) is less than 32 characters
        match /{imageId} {
          allow read;
          allow write: if request.resource.size < 5 * 1024 * 1024
                       && request.resource.contentType.matches('image/.*')
                       && request.resource.contentType == resource.contentType
                       && imageId.size() < 32
        }
      }
    }
  }

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