การจัดโครงสร้างกฎความปลอดภัยของ Cloud Firestore

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

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

การประกาศบริการและฐานข้อมูล

Cloud Firestore Security Rules ขึ้นต้นด้วยการประกาศต่อไปนี้เสมอ

service cloud.firestore {
  match /databases/{database}/documents {
    // ...
  }
}

การประกาศ service cloud.firestore จะกําหนดขอบเขตของกฎเป็น Cloud Firestore ซึ่งจะช่วยป้องกันไม่ให้ Cloud Firestore Security Rules ขัดแย้งกับกฎสําหรับผลิตภัณฑ์อื่นๆ เช่น Cloud Storage

การประกาศ match /databases/{database}/documents จะระบุว่ากฎควรตรงกับฐานข้อมูล Cloud Firestore ในโปรเจ็กต์ ปัจจุบันแต่ละโปรเจ็กต์มีฐานข้อมูลเพียงฐานข้อมูลเดียวชื่อ (default)

กฎพื้นฐานของการอ่าน/เขียน

กฎพื้นฐานประกอบด้วยคำสั่ง match ที่ระบุเส้นทางเอกสารและนิพจน์ allow ที่ระบุรายละเอียดว่าเมื่อใดที่อนุญาตให้อ่านข้อมูลที่ระบุ

service cloud.firestore {
  match /databases/{database}/documents {

    // Match any document in the 'cities' collection
    match /cities/{city} {
      allow read: if <condition>;
      allow write: if <condition>;
    }
  }
}

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

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

การดำเนินการแบบละเอียด

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

กฎ read สามารถแบ่งออกเป็น get และ list ส่วนกฎ write สามารถแบ่งออกเป็น create, update และ delete ดังนี้

service cloud.firestore {
  match /databases/{database}/documents {
    // A read rule can be divided into get and list rules
    match /cities/{city} {
      // Applies to single document read requests
      allow get: if <condition>;

      // Applies to queries and collection read requests
      allow list: if <condition>;
    }

    // A write rule can be divided into create, update, and delete rules
    match /cities/{city} {
      // Applies to writes to nonexistent documents
      allow create: if <condition>;

      // Applies to writes to existing documents
      allow update: if <condition>;

      // Applies to delete operations
      allow delete: if <condition>;
    }
  }
}

ข้อมูลแบบลําดับชั้น

ข้อมูลใน 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

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

เวอร์ชัน 1

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

ไวลด์การ์ดแบบย้อนกลับต้องอยู่ท้ายคำสั่งการจับคู่

เวอร์ชัน 2

ในกฎความปลอดภัยเวอร์ชัน 2 ไวลด์การ์ดแบบย้อนกลับจะจับคู่รายการเส้นทางตั้งแต่ 0 รายการขึ้นไป 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>;
    }
  }
}

คุณมีไวลด์การ์ดแบบย้อนกลับได้สูงสุด 1 รายการต่อคำสั่งการจับคู่ แต่ในเวอร์ชัน 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คำสั่งมากกว่า 1 รายการ ในกรณีที่นิพจน์ 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 เนื่องจากกฎที่ 2 เป็น true เสมอ แม้ว่ากฎที่ 1 จะเป็น false เสมอก็ตาม

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

โปรดคำนึงถึงขีดจำกัดต่อไปนี้เมื่อใช้กฎความปลอดภัย

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

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

หากเกินขีดจำกัดดังกล่าว ระบบจะแสดงข้อผิดพลาด "ถูกปฏิเสธสิทธิ์"

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

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

ขั้นตอนถัดไป