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

يمكنك استخدام 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 السماح بالوصول أو رفضه ديناميكيًا بناءً على المستند البيانات:

  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 هذا في هدف 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);
جافا
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 في المستندات المرجعية