سینتکس اصلی زبان قوانین امنیت پایگاه داده بیدرنگ را بیاموزید

قوانین امنیتی پایگاه داده بیدرنگ Firebase به شما امکان می دهد دسترسی به داده های ذخیره شده در پایگاه داده خود را کنترل کنید. سینتکس قوانین انعطاف پذیر به شما امکان می دهد قوانینی را ایجاد کنید که با هر چیزی مطابقت داشته باشد، از همه نوشته ها به پایگاه داده شما تا عملیات روی گره های جداگانه.

قوانین امنیت پایگاه داده بیدرنگ پیکربندی اعلامی برای پایگاه داده شما هستند. این بدان معناست که قوانین جدا از منطق محصول تعریف می شوند. این چند مزیت دارد: کلاینت‌ها مسئول اجرای امنیت نیستند، پیاده‌سازی‌های باگ داده‌های شما را به خطر نمی‌اندازند، و شاید مهم‌تر از همه، نیازی به داور میانی مانند سرور برای محافظت از داده‌ها در برابر جهان نیست.

این مبحث ساختار و نحو اساسی قوانین امنیتی پایگاه داده بیدرنگ را که برای ایجاد مجموعه قوانین کامل استفاده می شود، شرح می دهد.

ساختار قوانین امنیتی شما

قوانین امنیتی پایگاه داده بیدرنگ از عبارات جاوا اسکریپت مانند موجود در یک سند JSON تشکیل شده است. ساختار قوانین شما باید از ساختار داده هایی که در پایگاه داده خود ذخیره کرده اید پیروی کند.

قوانین اساسی مجموعه ای از گره ها را که باید ایمن شوند، روش های دسترسی (مثلاً خواندن، نوشتن) درگیر، و شرایطی که تحت آن دسترسی مجاز یا رد می شود، مشخص می کند. در مثال‌های زیر، شرایط ما عبارت‌های true و false ساده خواهد بود، اما در مبحث بعدی به روش‌های پویاتری برای بیان شرایط خواهیم پرداخت.

بنابراین، به عنوان مثال، اگر می‌خواهیم یک child_node تحت یک parent_node ایمن کنیم، نحو کلی که باید دنبال شود این است:

{
  "rules": {
    "parent_node": {
      "child_node": {
        ".read": <condition>,
        ".write": <condition>,
        ".validate": <condition>,
      }
    }
  }
}

بیایید این الگو را اعمال کنیم. به عنوان مثال، فرض کنید فهرستی از پیام‌ها را دنبال می‌کنید و داده‌هایی به شکل زیر دارید:

{
  "messages": {
    "message0": {
      "content": "Hello",
      "timestamp": 1405704370369
    },
    "message1": {
      "content": "Goodbye",
      "timestamp": 1405704395231
    },
    ...
  }
}

قوانین شما باید به روشی مشابه ساختاردهی شوند. در اینجا مجموعه ای از قوانین برای امنیت فقط خواندنی وجود دارد که ممکن است برای این ساختار داده منطقی باشد. این مثال نشان می‌دهد که چگونه گره‌های پایگاه‌داده را مشخص می‌کنیم که قوانین برای آن‌ها اعمال می‌شوند و شرایط ارزیابی قوانین در آن گره‌ها.

{
  "rules": {
    // For requests to access the 'messages' node...
    "messages": {
      // ...and the individual wildcarded 'message' nodes beneath
      // (we'll cover wildcarding variables more a bit later)....
      "$message": {

        // For each message, allow a read operation if <condition>. In this
        // case, we specify our condition as "true", so read access is always granted.
        ".read": "true",

        // For read-only behavior, we specify that for write operations, our
        // condition is false.
        ".write": "false"
      }
    }
  }
}

قوانین اساسی عملیات

سه نوع قانون برای اعمال امنیت بر اساس نوع عملیاتی که روی داده ها انجام می شود وجود دارد: .write ، .read و .validate . در اینجا خلاصه ای سریع از اهداف آنها آورده شده است:

انواع قوانین
.بخوانید توضیح می دهد که آیا و چه زمانی داده ها مجاز به خواندن توسط کاربران هستند.
.نوشتن توضیح می دهد که آیا و چه زمانی داده ها مجاز به نوشتن هستند.
اعتبار سنجی تعیین می کند که یک مقدار به درستی قالب بندی شده چگونه به نظر می رسد، آیا دارای ویژگی های فرزند و نوع داده است.

متغیرهای ضبط حروف عام

تمام عبارات قوانین به گره ها اشاره می کنند. یک دستور می‌تواند به یک گره خاص اشاره کند یا از متغیرهای ثبت علامت عام $ برای اشاره به مجموعه‌هایی از گره‌ها در سطح سلسله مراتب استفاده کند. از این متغیرهای ضبط برای ذخیره مقدار کلیدهای گره برای استفاده در دستورات قوانین بعدی استفاده کنید. این تکنیک به شما امکان می دهد شرایط پیچیده تر Rules بنویسید، چیزی که در مبحث بعدی با جزئیات بیشتر به آن خواهیم پرداخت.

{
  "rules": {
    "rooms": {
      // this rule applies to any child of /rooms/, the key for each room id
      // is stored inside $room_id variable for reference
      "$room_id": {
        "topic": {
          // the room's topic can be changed if the room id has "public" in it
          ".write": "$room_id.contains('public')"
        }
      }
    }
  }
}

متغیرهای پویا $ همچنین می توانند به موازات نام مسیرهای ثابت استفاده شوند. در این مثال، ما از متغیر $other برای اعلام یک قانون .validate استفاده می‌کنیم که تضمین می‌کند widget فرزند دیگری به جز title و color ندارد. هر نوشته ای که منجر به ایجاد فرزندان اضافی شود با شکست مواجه خواهد شد.

{
  "rules": {
    "widget": {
      // a widget can have a title or color attribute
      "title": { ".validate": true },
      "color": { ".validate": true },

      // but no other child paths are allowed
      // in this case, $other means any key excluding "title" and "color"
      "$other": { ".validate": false }
    }
  }
}

خواندن و نوشتن قوانین آبشار

قوانین .read و .write از بالا به پایین کار می کنند، با قوانین کم عمق تر که قوانین عمیق تر را نادیده می گیرند. اگر یک قانون مجوز خواندن یا نوشتن را در یک مسیر خاص اعطا کند، آنگاه به تمام گره های فرزند زیر آن نیز دسترسی می دهد. ساختار زیر را در نظر بگیرید:

{
  "rules": {
     "foo": {
        // allows read to /foo/*
        ".read": "data.child('baz').val() === true",
        "bar": {
          /* ignored, since read was allowed already */
          ".read": false
        }
     }
  }
}

این ساختار امنیتی به /bar/ اجازه می‌دهد تا هر زمان که /foo/ حاوی یک baz فرزند با مقدار true باشد خوانده شود. قانون ".read": false تحت /foo/bar/ در اینجا تأثیری ندارد، زیرا دسترسی را نمی توان با یک مسیر فرزند لغو کرد.

اگرچه ممکن است بلافاصله بصری به نظر نرسد، این بخش قدرتمندی از زبان قوانین است و اجازه می دهد تا امتیازات دسترسی بسیار پیچیده با حداقل تلاش اجرا شود. زمانی که بعداً در این راهنما وارد امنیت مبتنی بر کاربر شویم، این موضوع نشان داده خواهد شد.

توجه داشته باشید که قوانین .validate آبشاری نمی شوند. همه قوانین اعتبارسنجی باید در تمام سطوح سلسله مراتب رعایت شوند تا اجازه نوشتن داده شود.

قوانین فیلتر نیستند

قوانین به صورت اتمی اعمال می شوند. این بدان معنی است که اگر قانونی در آن مکان یا در یک مکان والد وجود نداشته باشد که به آن دسترسی بدهد، یک عملیات خواندن یا نوشتن بلافاصله با شکست مواجه می شود. حتی اگر هر مسیر کودک آسیب‌دیده قابل دسترسی باشد، خواندن در مکان والدین به‌طور کامل با شکست مواجه می‌شود. این ساختار را در نظر بگیرید:

{
  "rules": {
    "records": {
      "rec1": {
        ".read": true
      },
      "rec2": {
        ".read": false
      }
    }
  }
}

بدون درک اینکه قوانین به صورت اتمی ارزیابی می شوند، ممکن است به نظر برسد که واکشی مسیر /records/ rec1 را برمی گرداند اما نه rec2 . با این حال، نتیجه واقعی یک خطا است:

جاوا اسکریپت
var db = firebase.database();
db.ref("records").once("value", function(snap) {
  // success method is not called
}, function(err) {
  // error callback triggered with PERMISSION_DENIED
});
هدف-C
توجه: این محصول Firebase در هدف App Clip موجود نیست.
FIRDatabaseReference *ref = [[FIRDatabase database] reference];
[[_ref child:@"records"] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) {
  // success block is not called
} withCancelBlock:^(NSError * _Nonnull error) {
  // cancel block triggered with PERMISSION_DENIED
}];
سویفت
توجه: این محصول Firebase در هدف App Clip موجود نیست.
var ref = FIRDatabase.database().reference()
ref.child("records").observeSingleEventOfType(.Value, withBlock: { snapshot in
    // success block is not called
}, withCancelBlock: { error in
    // cancel block triggered with PERMISSION_DENIED
})
جاوا
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("records");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
  @Override
  public void onDataChange(DataSnapshot snapshot) {
    // success method is not called
  }

  @Override
  public void onCancelled(FirebaseError firebaseError) {
    // error callback triggered with PERMISSION_DENIED
  });
});
استراحت
curl https://docs-examples.firebaseio.com/rest/records/
# response returns a PERMISSION_DENIED error

از آنجایی که عملیات خواندن در /records/ اتمی است، و هیچ قانون خواندنی وجود ندارد که به همه داده‌های زیر /records/ دسترسی داشته باشد، این یک خطای PERMISSION_DENIED ایجاد می‌کند. اگر این قانون را در شبیه ساز امنیتی کنسول Firebase خود ارزیابی کنیم، می بینیم که عملیات خواندن رد شده است زیرا هیچ قانون خواندنی اجازه دسترسی به مسیر /records/ را نمی دهد. با این حال، توجه داشته باشید که قانون rec1 هرگز ارزیابی نشد زیرا در مسیر درخواستی ما قرار نداشت. برای واکشی rec1 ، باید مستقیماً به آن دسترسی داشته باشیم:

جاوا اسکریپت
var db = firebase.database();
db.ref("records/rec1").once("value", function(snap) {
  // SUCCESS!
}, function(err) {
  // error callback is not called
});
هدف-C
توجه: این محصول Firebase در هدف App Clip موجود نیست.
FIRDatabaseReference *ref = [[FIRDatabase database] reference];
[[ref child:@"records/rec1"] observeSingleEventOfType:FEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) {
    // SUCCESS!
}];
سویفت
توجه: این محصول Firebase در هدف App Clip موجود نیست.
var ref = FIRDatabase.database().reference()
ref.child("records/rec1").observeSingleEventOfType(.Value, withBlock: { snapshot in
    // SUCCESS!
})
جاوا
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("records/rec1");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
  @Override
  public void onDataChange(DataSnapshot snapshot) {
    // SUCCESS!
  }

  @Override
  public void onCancelled(FirebaseError firebaseError) {
    // error callback is not called
  }
});
استراحت
curl https://docs-examples.firebaseio.com/rest/records/rec1
# SUCCESS!

اظهارات همپوشانی

این امکان وجود دارد که بیش از یک قانون برای یک گره اعمال شود. در موردی که عبارات قوانین متعدد یک گره را شناسایی می‌کنند، اگر هر یک از شرایط false باشد، روش دسترسی رد می‌شود:

{
  "rules": {
    "messages": {
      // A rule expression that applies to all nodes in the 'messages' node
      "$message": {
        ".read": "true",
        ".write": "true"
      },
      // A second rule expression applying specifically to the 'message1` node
      "message1": {
        ".read": "false",
        ".write": "false"
      }
    }
  }
}

در مثال بالا، خواندن گره message1 رد می شود زیرا قانون دوم همیشه false است، حتی اگر قانون اول همیشه true باشد.

مراحل بعدی

می توانید درک خود را از قوانین امنیتی پایگاه داده بیدرنگ Firebase عمیق تر کنید:

  • مفهوم اصلی بعدی زبان Rules ، شرایط پویا را بیاموزید، که به Rules شما اجازه می‌دهد مجوز کاربر را بررسی کنند، داده‌های موجود و ورودی را مقایسه کنند، داده‌های دریافتی را اعتبارسنجی کنند، ساختار جستارهای ارسال شده از مشتری و موارد دیگر را بررسی کنند.

  • موارد استفاده امنیتی معمولی و تعاریف قوانین امنیتی Firebase را که به آنها رسیدگی می کند، مرور کنید.