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

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

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

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

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/{allFiles=**} {
      // Disallow
        allow create: if !("ranking" in request.resource.metadata)
      }
    }
  }

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

Cloud Firestore

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

  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 لفرض هياكل البيانات والتحقّق من تنسيق البيانات ومحتواها. 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 هذا في استهداف تطبيق 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 هذا في استهداف تطبيق 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);
جافا
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 /{allImages=**} {
          // 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 {
        // Cascade read to any image type at any path
        match /{allImages=**} {
          allow read;
        }

        // 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) File name (stored in imageId wildcard variable) is less than 32 characters
        match /{imageId} {
          allow write: if request.resource.size < 5 * 1024 * 1024
                       && request.resource.contentType.matches('image/.*')
                       && request.resource.contentType == resource.contentType
                       && imageId.size() < 32
        }
      }
    }
  }

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