Check out what’s new from Firebase at Google I/O 2022. Learn more

กฎความปลอดภัยทำงานอย่างไร

ความปลอดภัยอาจเป็นหนึ่งในส่วนที่ซับซ้อนที่สุดของปริศนาการพัฒนาแอป ในแอปพลิเคชันส่วนใหญ่ นักพัฒนาต้องสร้างและเรียกใช้เซิร์ฟเวอร์ที่จัดการการรับรองความถูกต้อง (ใครคือผู้ใช้) และการอนุญาต (สิ่งที่ผู้ใช้สามารถทำได้)

กฎความปลอดภัยของ Firebase ลบเลเยอร์กลาง (เซิร์ฟเวอร์) และอนุญาตให้คุณระบุสิทธิ์ตามเส้นทางสำหรับไคลเอ็นต์ที่เชื่อมต่อกับข้อมูลของคุณโดยตรง ใช้คู่มือนี้เพื่อเรียนรู้เพิ่มเติมเกี่ยวกับวิธีการใช้กฎกับคำขอที่เข้ามา

เลือกผลิตภัณฑ์เพื่อเรียนรู้เพิ่มเติมเกี่ยวกับกฎของผลิตภัณฑ์

Cloud Firestore

โครงสร้างพื้นฐาน

กฎความปลอดภัยของ Firebase ใน Cloud Firestore และ Cloud Storage ใช้โครงสร้างและไวยากรณ์ต่อไปนี้:

service <<name>> {
  // Match the resource path.
  match <<path>> {
    // Allow the request if the following conditions are true.
    allow <<methods>> : if <<condition>>
  }
}

แนวคิดหลักต่อไปนี้มีความสำคัญในการทำความเข้าใจเมื่อคุณสร้างกฎ:

  • คำขอ: เมธอดหรือเมธอดที่เรียกใช้ในคำสั่ง allow นี่คือวิธีการที่คุณอนุญาตให้เรียกใช้ วิธีการมาตรฐานคือ: get , list , create , update และ delete วิธีการอำนวยความสะดวกในการ read และ write ช่วยให้สามารถเข้าถึงการอ่านและเขียนในวงกว้างบนฐานข้อมูลที่ระบุหรือเส้นทางการจัดเก็บ
  • เส้นทาง: ฐานข้อมูลหรือตำแหน่งที่เก็บข้อมูล แสดงเป็นเส้นทาง URI
  • กฎ: คำสั่ง allow ซึ่งรวมถึงเงื่อนไขที่อนุญาตคำขอหากประเมินเป็นจริง

กฎความปลอดภัยรุ่น2

ตั้งแต่เดือนพฤษภาคม 2019 เป็นต้นไป กฎความปลอดภัยของ Firebase เวอร์ชัน 2 พร้อมให้บริการแล้ว กฎเวอร์ชัน 2 เปลี่ยนพฤติกรรมของ สัญลักษณ์แทนแบบเรียกซ้ำ {name=**} คุณต้องใช้เวอร์ชัน 2 หากคุณวางแผนที่จะใช้ แบบสอบถามกลุ่มคอลเลกชัน คุณต้องเลือกใช้เวอร์ชัน 2 โดยสร้าง rules_version = '2'; บรรทัดแรกในกฎความปลอดภัยของคุณ:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {

เส้นทางที่ตรงกัน

คำชี้แจงการแข่งขันทั้งหมดควรชี้ไปที่เอกสาร ไม่ใช่การรวบรวม คำสั่งจับคู่สามารถชี้ไปที่เอกสารเฉพาะ เช่นใน match /cities/SF หรือใช้สัญลักษณ์แทนเพื่อชี้ไปที่เอกสารใดๆ ในเส้นทางที่ระบุ เช่นเดียวกับใน match /cities/{city}

ในตัวอย่างข้างต้น คำสั่งการจับคู่ใช้ไวยากรณ์สัญลักษณ์แทน {city} ซึ่งหมายความว่ากฎจะใช้กับเอกสารใดๆ ในกลุ่ม cities เช่น /cities/SF หรือ /cities/NYC เมื่อประเมินนิพจน์ที่ allow ในคำสั่งการจับคู่ ตัวแปร city จะแก้ไขเป็นชื่อเอกสารเมือง เช่น SF หรือ NYC

จับคู่คอลเลกชันย่อย

ข้อมูลใน Cloud Firestore ถูกจัดระเบียบเป็นคอลเล็กชันของเอกสาร และแต่ละเอกสารอาจขยายลำดับชั้นผ่านคอลเล็กชันย่อย สิ่งสำคัญคือต้องเข้าใจว่ากฎความปลอดภัยโต้ตอบกับข้อมูลแบบลำดับชั้นอย่างไร

พิจารณาสถานการณ์ที่เอกสารแต่ละฉบับในคอลเล็กชัน cities ประกอบด้วยคอลเล็กชันย่อยของ landmarks กฎความปลอดภัยใช้เฉพาะที่พาธที่ตรงกัน ดังนั้นการควบคุมการเข้าถึงที่กำหนดไว้ในคอลเล็กชัน cities จะไม่มีผลกับการรวบรวมย่อยของ landmarks ให้เขียนกฎที่ชัดเจนเพื่อควบคุมการเข้าถึงคอลเล็กชันย่อยแทน:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      allow read, write: if <condition>;

      // Explicitly define rules for the 'landmarks' subcollection
      match /landmarks/{landmark} {
        allow read, write: if <condition>;
      }
    }
  }
}

เมื่อซ้อนคำสั่ง match เส้นทางของคำสั่ง match ภายในจะสัมพันธ์กับเส้นทางของคำสั่ง match ภายนอกเสมอ ดังนั้นชุดกฎต่อไปนี้จึงเทียบเท่า:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      match /landmarks/{landmark} {
        allow read, write: if <condition>;
      }
    }
  }
}
service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city}/landmarks/{landmark} {
      allow read, write: if <condition>;
    }
  }
}

สัญลักษณ์แทนแบบเรียกซ้ำ

หากคุณต้องการให้กฎนำไปใช้กับลำดับชั้นลึกตามอำเภอใจ ให้ใช้ไวยากรณ์สัญลักษณ์แทนแบบเรียกซ้ำ {name=**} :

service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the cities collection as well as any document
    // in a subcollection.
    match /cities/{document=**} {
      allow read, write: if <condition>;
    }
  }
}

เมื่อใช้ไวยากรณ์ไวด์การ์ดแบบเรียกซ้ำ ตัวแปรไวด์การ์ดจะมีเซ็กเมนต์พาธที่ตรงกันทั้งหมด แม้ว่าเอกสารจะอยู่ในคอลเลกชั่นย่อยที่ซ้อนกันอย่างลึกล้ำ ตัวอย่างเช่น กฎที่แสดงด้านบนจะตรงกับเอกสารที่ตั้งอยู่ที่ /cities/SF/landmarks/coit_tower และค่าของตัวแปร document จะเป็น SF/landmarks/coit_tower

อย่างไรก็ตาม โปรดทราบว่าลักษณะการทำงานของ wildcard แบบเรียกซ้ำนั้นขึ้นอยู่กับเวอร์ชันของกฎ

เวอร์ชั่น 1

กฎความปลอดภัยใช้เวอร์ชัน 1 โดยค่าเริ่มต้น ในเวอร์ชัน 1 อักขระตัวแทนแบบเรียกซ้ำจะจับคู่รายการพาธตั้งแต่หนึ่งรายการขึ้นไป ไม่ตรงกับเส้นทางที่ว่างเปล่า ดังนั้น match /cities/{city}/{document=**} จะจับคู่เอกสารในคอลเล็กชันย่อยแต่ไม่จับคู่ในคอลเล็กชัน cities ในขณะที่ match /cities/{document=**} จะจับคู่เอกสารทั้งสองใน คอลเลกชัน cities และคอลเลกชันย่อย

สัญลักษณ์แทนแบบเรียกซ้ำต้องอยู่ท้ายคำสั่งการแข่งขัน

รุ่น2

ในกฎความปลอดภัยเวอร์ชัน 2 ไวด์การ์ดแบบเรียกซ้ำจะจับคู่รายการพาธศูนย์หรือมากกว่า match/cities/{city}/{document=**} จับคู่เอกสารในคอลเลกชันย่อยใดๆ เช่นเดียวกับเอกสารในคอลเลกชัน cities

คุณต้องเลือกใช้เวอร์ชัน 2 โดยเพิ่ม rules_version = '2'; ที่ด้านบนสุดของกฎความปลอดภัยของคุณ:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the cities collection as well as any document
    // in a subcollection.
    match /cities/{city}/{document=**} {
      allow read, write: if <condition>;
    }
  }
}

คุณสามารถมีสัญลักษณ์แทนแบบเรียกซ้ำได้มากสุดหนึ่งรายการต่อคำสั่งการจับคู่ แต่ในเวอร์ชัน 2 คุณสามารถวางสัญลักษณ์ตัวแทนนี้ไว้ที่ใดก็ได้ในคำสั่งจับคู่ ตัวอย่างเช่น:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the songs collection group
    match /{path=**}/songs/{song} {
      allow read, write: if <condition>;
    }
  }
}

ถ้าคุณใช้การ สืบค้นกลุ่มคอลเลกชัน คุณต้องใช้เวอร์ชัน 2 โปรดดู การรักษาความปลอดภัยการสืบค้นกลุ่มคอลเลกชัน

คำชี้แจงการแข่งขันที่ทับซ้อนกัน

เป็นไปได้ที่เอกสารจะจับคู่คำสั่งที่ match มากกว่าหนึ่งคำสั่ง ในกรณีที่นิพจน์ allow หลายรายการตรงกับคำขอ การเข้าถึงจะได้รับอนุญาตหากมีเงื่อนไข ใด ๆ ที่เป็น true :

service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the 'cities' collection.
    match /cities/{city} {
      allow read, write: if false;
    }

    // Matches any document in the 'cities' collection or subcollections.
    match /cities/{document=**} {
      allow read, write: if true;
    }
  }
}

ในตัวอย่างข้างต้น การอ่านและเขียนทั้งหมดในคอลเล็กชัน cities จะได้รับอนุญาต เนื่องจากกฎข้อที่สองเป็น true เสมอ แม้ว่ากฎข้อแรกจะเป็น false เสมอ

ขีดจำกัดกฎความปลอดภัย

ขณะที่คุณทำงานกับกฎความปลอดภัย ให้สังเกตข้อจำกัดต่อไปนี้:

ขีดจำกัด รายละเอียด
จำนวนสูงสุดของการโทรที่ exists() , get() และ getAfter() การโทรต่อคำขอ
  • 10 สำหรับคำขอเอกสารเดียวและคำขอค้นหา
  • 20 สำหรับการอ่านเอกสารหลายรายการ ธุรกรรม และการเขียนแบบแบตช์ ขีดจำกัดก่อนหน้าที่ 10 ยังใช้กับการดำเนินการแต่ละครั้ง

    ตัวอย่างเช่น สมมติว่าคุณสร้างคำขอเขียนเป็นชุดโดยมีการดำเนินการเขียน 3 รายการ และกฎความปลอดภัยใช้การเรียกการเข้าถึงเอกสาร 2 รายการเพื่อตรวจสอบความถูกต้องของการเขียนแต่ละครั้ง ในกรณีนี้ การเขียนแต่ละครั้งจะใช้การเรียกการเข้าถึง 2 ใน 10 รายการ และคำขอเขียนแบบแบตช์ใช้ 6 รายการจาก 20 การเรียกการเข้าถึง

เกินขีดจำกัดอย่างใดอย่างหนึ่งส่งผลให้เกิดข้อผิดพลาดในการปฏิเสธการอนุญาต

การโทรเข้าถึงเอกสารบางรายการอาจถูกแคชไว้ และการเรียกใช้ที่แคชจะไม่นับรวมในขีดจำกัด

ความลึกคำสั่ง match ซ้อนกันสูงสุด 10
ความยาวเส้นทางสูงสุด ในส่วนของเส้นทาง อนุญาตภายในชุดคำสั่ง match ที่ซ้อนกัน 100
จำนวนตัวแปรการดักจับเส้นทางสูงสุดที่อนุญาตภายในชุดคำสั่ง match ที่ซ้อนกัน 20
ความลึกของการเรียกฟังก์ชันสูงสุด 20
จำนวนอาร์กิวเมนต์ฟังก์ชันสูงสุด 7
จำนวนสูงสุดของการโยงตัวแปร let ต่อฟังก์ชัน 10
จำนวนสูงสุดของการเรียกฟังก์ชันแบบเรียกซ้ำหรือแบบวนซ้ำ 0 (ไม่อนุญาต)
จำนวนนิพจน์สูงสุดที่ประเมินต่อคำขอ 1,000
ขนาดสูงสุดของชุดกฎ ชุดกฎต้องเป็นไปตามขีดจำกัดสองขนาด:
  • ขีดจำกัด 256 KB สำหรับขนาดของแหล่งข้อความชุดกฎที่เผยแพร่จากคอนโซล Firebase หรือจาก CLI โดยใช้ firebase deploy
  • ขีดจำกัดขนาด 250 KB ของชุดกฎที่คอมไพล์ซึ่งส่งผลให้ Firebase ประมวลผลซอร์สและทำให้ใช้งานได้ที่ส่วนหลัง

การจัดเก็บเมฆ

โครงสร้างพื้นฐาน

กฎความปลอดภัยของ Firebase ใน Cloud Firestore และ Cloud Storage ใช้โครงสร้างและไวยากรณ์ต่อไปนี้:

service <<name>> {
  // Match the resource path.
  match <<path>> {
    // Allow the request if the following conditions are true.
    allow <<methods>> : if <<condition>>
  }
}

แนวคิดหลักต่อไปนี้มีความสำคัญในการทำความเข้าใจเมื่อคุณสร้างกฎ:

  • คำขอ: เมธอดหรือเมธอดที่เรียกใช้ในคำสั่ง allow นี่คือวิธีการที่คุณอนุญาตให้เรียกใช้ วิธีการมาตรฐานคือ: get , list , create , update และ delete วิธีการอำนวยความสะดวกในการ read และ write ช่วยให้สามารถเข้าถึงการอ่านและเขียนในวงกว้างบนฐานข้อมูลที่ระบุหรือเส้นทางการจัดเก็บ
  • เส้นทาง: ฐานข้อมูลหรือตำแหน่งที่เก็บข้อมูล แสดงเป็นเส้นทาง URI
  • กฎ: คำสั่ง allow ซึ่งรวมถึงเงื่อนไขที่อนุญาตคำขอหากประเมินเป็นจริง

เส้นทางที่ตรงกัน

กฎความปลอดภัยของ Cloud Storage match กับเส้นทางของไฟล์ที่ใช้ในการเข้าถึงไฟล์ใน Cloud Storage กฎสามารถ match เส้นทางที่แน่นอนหรือเส้นทางตัวแทน และกฎยังสามารถซ้อนกันได้ หากไม่มีกฎการจับคู่ที่อนุญาตให้ใช้วิธีคำขอ หรือเงื่อนไขประเมิน false คำขอจะถูกปฏิเสธ

ตรงกันทั้งหมด

// Exact match for "images/profilePhoto.png"
match /images/profilePhoto.png {
  allow write: if <condition>;
}

// Exact match for "images/croppedProfilePhoto.png"
match /images/croppedProfilePhoto.png {
  allow write: if <other_condition>;
}

ไม้ขีดที่ซ้อนกัน

// Partial match for files that start with "images"
match /images {
  // Exact match for "images/profilePhoto.png"
  match /profilePhoto.png {
    allow write: if <condition>;
  }

  // Exact match for "images/croppedProfilePhoto.png"
  match /croppedProfilePhoto.png {
    allow write: if <other_condition>;
  }
}

แมตช์ไวลด์การ์ด

กฎยังสามารถใช้เพื่อ match รูปแบบโดยใช้สัญลักษณ์แทน ไวด์การ์ดเป็นตัวแปรที่มีชื่อซึ่งแสดงถึงสตริงเดียว เช่น profilePhoto.png หรือหลายเซ็กเมนต์พาธ เช่น images/profilePhoto.png

wildcard ถูกสร้างขึ้นโดยการเพิ่มวงเล็บปีกการอบๆ ชื่อ wildcard เช่น {string} สามารถประกาศไวด์การ์ดหลายเซ็กเมนต์ได้โดยการเพิ่ม =** ให้กับชื่อไวด์การ์ด เช่น {path=**} :

// Partial match for files that start with "images"
match /images {
  // Exact match for "images/*"
  // e.g. images/profilePhoto.png is matched
  match /{imageId} {
    // This rule only matches a single path segment (*)
    // imageId is a string that contains the specific segment matched
    allow read: if <condition>;
  }

  // Exact match for "images/**"
  // e.g. images/users/user:12345/profilePhoto.png is matched
  // images/profilePhoto.png is also matched!
  match /{allImages=**} {
    // This rule matches one or more path segments (**)
    // allImages is a path that contains all segments matched
    allow read: if <other_condition>;
  }
}

หากกฎหลายข้อตรงกับไฟล์ ผลลัพธ์จะเป็น OR ของผลลัพธ์ของการประเมินกฎทั้งหมด นั่นคือ ถ้ากฎใด ๆ ที่ไฟล์ตรงกับค่า true ผลลัพธ์จะเป็น true

ในกฎข้างต้น ไฟล์ "images/profilePhoto.png" สามารถอ่านได้หาก condition หรือเงื่อนไขอื่น ๆ ประเมินว่าเป็นจริง ในขณะที่ไฟล์ "images/users/user:12345/profilePhoto.png" จะขึ้นอยู่กับผลลัพธ์ของ other_condition other_condition .

ตัวแปรไวด์การ์ดสามารถอ้างอิงได้จากการ match ชื่อไฟล์หรือการอนุญาตเส้นทาง:

// Another way to restrict the name of a file
match /images/{imageId} {
  allow read: if imageId == "profilePhoto.png";
}

กฎความปลอดภัยของ Cloud Storage ไม่ต่อเรียง และกฎจะได้รับการประเมินเมื่อเส้นทางคำขอตรงกับเส้นทางที่มีกฎที่ระบุเท่านั้น

ขอการประเมิน

การอัปโหลด ดาวน์โหลด การเปลี่ยนแปลงข้อมูลเมตา และการลบจะได้รับการประเมินโดยใช้ request ที่ส่งไปยัง Cloud Storage ตัวแปร request ประกอบด้วยเส้นทางของไฟล์ที่ดำเนินการตามคำขอ เวลาที่รับคำขอ และค่า resource ใหม่หากคำขอเป็นการเขียน รวมส่วนหัว HTTP และสถานะการตรวจสอบสิทธิ์ด้วย

ออบเจ็กต์ request ยังมี ID เฉพาะของผู้ใช้และเพย์โหลดการตรวจสอบสิทธิ์ Firebase ในอ็อบเจ็กต์ request.auth ซึ่งจะอธิบายเพิ่มเติมในส่วนการ ตรวจสอบสิทธิ์ ของเอกสาร

รายการคุณสมบัติทั้งหมดในวัตถุ request มีอยู่ด้านล่าง:

คุณสมบัติ พิมพ์ คำอธิบาย
auth แผนที่<สตริง สตริง> เมื่อผู้ใช้เข้าสู่ระบบ ให้ระบุ uid ID เฉพาะของผู้ใช้ และ token แผนที่ของ Firebase Authentication JWT อ้างสิทธิ์ มิฉะนั้นจะเป็น null
params แผนที่<สตริง สตริง> แผนที่ที่มีพารามิเตอร์การค้นหาของคำขอ
path เส้นทาง path ที่แสดงเส้นทางที่ร้องขอกำลังดำเนินการอยู่
resource แผนที่<สตริง สตริง> ค่าทรัพยากรใหม่ แสดงเฉพาะในคำขอ write
time การประทับเวลา การประทับเวลาที่แสดงเวลาเซิร์ฟเวอร์ที่คำขอได้รับการประเมิน

การประเมินทรัพยากร

เมื่อประเมินกฎ คุณอาจต้องการประเมินข้อมูลเมตาของไฟล์ที่กำลังอัปโหลด ดาวน์โหลด แก้ไข หรือลบ วิธีนี้ช่วยให้คุณสร้างกฎที่ซับซ้อนและมีประสิทธิภาพซึ่งทำสิ่งต่างๆ เช่น อนุญาตให้อัปโหลดเฉพาะไฟล์ที่มีเนื้อหาบางประเภท หรือลบเฉพาะไฟล์ที่มีขนาดใหญ่กว่าขนาดที่กำหนด

กฎความปลอดภัยของ Firebase สำหรับ Cloud Storage ให้ข้อมูลเมตาของไฟล์ในออบเจ็กต์ resource ซึ่งประกอบด้วยคู่คีย์/ค่าของข้อมูลเมตาที่แสดงในออบเจ็กต์ Cloud Storage คุณสมบัติเหล่านี้สามารถตรวจสอบได้ในคำขอ read หรือ write เพื่อรับรองความถูกต้องของข้อมูล

ในคำขอ write (เช่น การอัปโหลด การอัปเดตข้อมูลเมตา และการลบ) นอกเหนือจากออบเจ็กต์ resource ซึ่งมีข้อมูลเมตาของไฟล์สำหรับไฟล์ที่มีอยู่ในปัจจุบันที่เส้นทางคำขอ คุณยังมีความสามารถในการใช้อ็อบเจ็กต์ request.resource ซึ่งมีชุดย่อยของข้อมูลเมตาของไฟล์ที่จะเขียนหากอนุญาตให้เขียน คุณสามารถใช้สองค่านี้เพื่อรับรองความถูกต้องของข้อมูลหรือบังคับใช้ข้อจำกัดของแอปพลิเคชัน เช่น ประเภทหรือขนาดไฟล์

รายการคุณสมบัติทั้งหมดในวัตถุ resource มีอยู่ด้านล่าง:

คุณสมบัติ พิมพ์ คำอธิบาย
name สตริง ชื่อเต็มของวัตถุ
bucket สตริง ชื่อของบัคเก็ตที่วัตถุนี้อยู่
generation int การ สร้างวัตถุ Google Cloud Storage ของวัตถุนี้
metageneration int การสร้าง เมตาอ็อบเจ็กต์ Google Cloud Storage ของออบเจ็กต์นี้
size int ขนาดของวัตถุเป็นไบต์
timeCreated การประทับเวลา การประทับเวลาแสดงเวลาที่วัตถุถูกสร้างขึ้น
updated การประทับเวลา การประทับเวลาแสดงเวลาที่วัตถุได้รับการอัปเดตครั้งล่าสุด
md5Hash สตริง แฮช MD5 ของอ็อบเจ็กต์
crc32c สตริง แฮช crc32c ของอ็อบเจ็กต์
etag สตริง etag ที่เกี่ยวข้องกับวัตถุนี้
contentDisposition สตริง การจัดการเนื้อหาที่เกี่ยวข้องกับวัตถุนี้
contentEncoding สตริง การเข้ารหัสเนื้อหาที่เกี่ยวข้องกับวัตถุนี้
contentLanguage สตริง ภาษาของเนื้อหาที่เกี่ยวข้องกับวัตถุนี้
contentType สตริง ชนิดเนื้อหาที่เกี่ยวข้องกับวัตถุนี้
metadata แผนที่<สตริง สตริง> คู่คีย์/ค่าของข้อมูลเมตาที่กำหนดเองเพิ่มเติมที่นักพัฒนาระบุ

request.resource มีสิ่งเหล่านี้ทั้งหมด ยกเว้น generation , metageneration , etag , timeCreated และ updated

ตัวอย่างเต็ม

เมื่อนำทุกอย่างมารวมกัน คุณสามารถสร้างตัวอย่างกฎสำหรับโซลูชันการจัดเก็บรูปภาพทั้งหมดได้:

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
     }
   }
 }
}

ฐานข้อมูลเรียลไทม์

โครงสร้างพื้นฐาน

ในฐานข้อมูลแบบเรียลไทม์ กฎความปลอดภัยของ Firebase ประกอบด้วยนิพจน์ที่เหมือน JavaScript ที่มีอยู่ในเอกสาร JSON

พวกเขาใช้ไวยากรณ์ต่อไปนี้:

{
  "rules": {
    "<<path>>": {
    // Allow the request if the condition for each method is true.
      ".read": <<condition>>,
      ".write": <<condition>>,
      ".validate": <<condition>>
    }
  }
}

มีองค์ประกอบพื้นฐานสามประการในกฎ:

  • เส้นทาง: ตำแหน่งฐานข้อมูล สิ่งนี้สะท้อนโครงสร้าง JSON ของฐานข้อมูลของคุณ
  • คำขอ: นี่คือวิธีที่กฎใช้ในการให้สิทธิ์การเข้าถึง กฎการ read และ write ให้สิทธิ์การเข้าถึงแบบอ่านและเขียนในวงกว้าง ในขณะที่กฎการ validate จะทำหน้าที่เป็นการยืนยันรองเพื่อให้สิทธิ์การเข้าถึงตามข้อมูลขาเข้าหรือที่มีอยู่
  • เงื่อนไข: เงื่อนไขที่อนุญาตคำขอหากประเมินว่าเป็นจริง

กฎเกณฑ์ที่ใช้กับเส้นทางอย่างไร

ในฐานข้อมูลเรียลไทม์ กฎจะใช้อะตอมมิก หมายความว่ากฎที่โหนดระดับบนสุดจะแทนที่กฎที่โหนดย่อยที่ละเอียดยิ่งขึ้น และกฎที่โหนดที่ลึกกว่านั้นไม่สามารถให้สิทธิ์การเข้าถึงเส้นทางหลักได้ คุณไม่สามารถปรับแต่งหรือเพิกถอนการเข้าถึงในเส้นทางที่ลึกกว่าในโครงสร้างฐานข้อมูลของคุณได้ ถ้าคุณได้ให้สิทธิ์การเข้าถึงสำหรับพาธพาเรนต์อันใดอันหนึ่งแล้ว

พิจารณากฎต่อไปนี้:

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

โครงสร้างความปลอดภัยนี้อนุญาตให้อ่าน /bar/ bar/ เมื่อใดก็ตามที่ /foo/ มี baz ลูกที่มีค่า true ".read": false ภายใต้ /foo/bar/ ไม่มีผลที่นี่ เนื่องจากเส้นทางลูกไม่สามารถเพิกถอนการเข้าถึงได้

แม้ว่าอาจดูเหมือนไม่เข้าใจง่ายในทันที แต่นี่เป็นส่วนที่มีประสิทธิภาพของภาษาของกฎและช่วยให้สามารถใช้สิทธิ์การเข้าถึงที่ซับซ้อนมากได้โดยใช้ความพยายามเพียงเล็กน้อย ซึ่งจะเป็นประโยชน์อย่างยิ่งต่อ การรักษาความปลอดภัยแบบอิงตามผู้ใช้

อย่างไรก็ตาม กฎ .validate จะไม่เรียงต่อกัน กฎการตรวจสอบทั้งหมดต้องเป็นไปตามลำดับชั้นทุกระดับจึงจะอนุญาตให้เขียนได้

นอกจากนี้ เนื่องจากกฎจะไม่นำไปใช้กับพาธพาเรนต์ การดำเนินการอ่านหรือเขียนจะล้มเหลวหากไม่มีกฎที่ตำแหน่งที่ร้องขอหรือที่ตำแหน่งพาเรนต์ที่ให้สิทธิ์การเข้าถึง แม้ว่าทุกเส้นทางย่อยที่ได้รับผลกระทบจะสามารถเข้าถึงได้ การอ่านที่ตำแหน่งหลักจะล้มเหลวโดยสิ้นเชิง พิจารณาโครงสร้างนี้:

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

หากไม่เข้าใจว่ามีการประเมินกฎแบบปรมาณู อาจดูเหมือนการดึงข้อมูลเส้นทาง /records/ จะส่งคืน rec1 แต่ไม่ใช่ rec2 อย่างไรก็ตาม ผลลัพธ์ที่แท้จริงนั้นเป็นข้อผิดพลาด:

JavaScript
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
}];
Swift
หมายเหตุ: ผลิตภัณฑ์ 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
})
Java
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 เราจะเห็นว่าการดำเนินการอ่านถูกปฏิเสธ:

Attempt to read /records with auth=Success(null)
    /
    /records

No .read rule allowed the operation.
Read was denied.

การดำเนินการถูกปฏิเสธเนื่องจากไม่มีกฎการอ่านที่อนุญาตให้เข้าถึงเส้นทาง /records/ แต่โปรดทราบว่ากฎสำหรับ rec1 ไม่เคยได้รับการประเมินเนื่องจากไม่อยู่ในเส้นทางที่เราขอ ในการดึงข้อมูล rec1 เราจะต้องเข้าถึงโดยตรง:

JavaScript
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!
}];
Swift
หมายเหตุ: ผลิตภัณฑ์ Firebase นี้ไม่มีในเป้าหมาย App Clip
var ref = FIRDatabase.database().reference()
ref.child("records/rec1").observeSingleEventOfType(.Value, withBlock: { snapshot in
    // SUCCESS!
})
Java
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!

ตัวแปรตำแหน่ง

กฎฐานข้อมูลเรียลไทม์สนับสนุนตัวแปร $location เพื่อจับคู่เซกเมนต์พาธ ใช้ $ นำหน้าส่วนเส้นทางของคุณเพื่อจับคู่กฎของคุณกับโหนดย่อยตามเส้นทาง

  {
    "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')"
          }
        }
      }
    }
  }

คุณสามารถใช้ $variable ควบคู่ไปกับชื่อพาธคงที่ได้

  {
    "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 }
      }
    }
  }