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

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

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

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

กฎความปลอดภัยของ Cloud Firestore จะเริ่มต้นด้วยการประกาศต่อไปนี้เสมอ:

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

การประกาศ service cloud.firestore จะกำหนดขอบเขตกฎไปยัง Cloud Firestore เพื่อป้องกันความขัดแย้งระหว่างกฎความปลอดภัยของ Cloud Firestore และกฎสำหรับผลิตภัณฑ์อื่นๆ เช่น 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 ไวด์การ์ดแบบเรียกซ้ำจะจับคู่รายการพาธตั้งแต่หนึ่งรายการขึ้นไป ไม่ตรงกับเส้นทางว่าง ดังนั้น 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
ขนาดสูงสุดของชุดกฎ ชุดกฎต้องเป็นไปตามขีดจำกัดขนาด 2 ประการ:
  • ขีดจำกัด 256 KB สำหรับขนาดของแหล่งข้อความชุดกฎที่เผยแพร่จากคอนโซล Firebase หรือจาก CLI โดยใช้ firebase deploy ใช้
  • ขีดจำกัดขนาด 250 KB สำหรับขนาดของชุดกฎที่คอมไพล์แล้วซึ่งเป็นผลเมื่อ Firebase ประมวลผลแหล่งที่มาและทำให้ใช้งานบนแบ็คเอนด์

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