Cloud Firestore Security Rules ช่วยให้คุณควบคุมการเข้าถึงเอกสารและ คอลเล็กชันในฐานข้อมูลได้ ไวยากรณ์กฎที่ยืดหยุ่นช่วยให้คุณสร้างกฎที่ตรงกับทุกอย่าง ตั้งแต่การเขียนทั้งหมดลงในฐานข้อมูลทั้งหมด ไปจนถึงการดำเนินการกับเอกสารที่เฉพาะเจาะจง
คู่มือนี้จะอธิบายไวยากรณ์และโครงสร้างพื้นฐานของกฎความปลอดภัย รวม ไวยากรณ์นี้กับ เงื่อนไขกฎความปลอดภัย เพื่อสร้าง ชุดกฎที่สมบูรณ์
การประกาศบริการและฐานข้อมูล
Cloud Firestore Security Rules จะเริ่มต้นด้วยการประกาศต่อไปนี้เสมอ
service cloud.firestore {
// The {database} wildcard allows the rules to reference any database,
// but these rules are only active on databases where they are explicitly deployed.
match /databases/{database}/documents {
// ...
}
}การประกาศ service cloud.firestore จะกำหนดขอบเขตของกฎเป็น
Cloud Firestore ซึ่งป้องกันความขัดแย้งระหว่าง Cloud Firestore Security Rules และ
กฎสำหรับผลิตภัณฑ์อื่นๆ เช่น Cloud Storage
การประกาศ match /databases/{database}/documents จะระบุว่ากฎ
ควรตรงกับฐานข้อมูล Cloud Firestore ใดก็ได้ในโปรเจ็กต์ แม้ว่าโปรเจ็กต์จะมีฐานข้อมูลได้สูงสุด 100 รายการ แต่ระบบจะกำหนดให้ฐานข้อมูลแรกที่สร้างเป็นฐานข้อมูลเริ่มต้นเท่านั้น
Cloud Firestore Security Rules จะถูกนำไปใช้แยกกันสำหรับฐานข้อมูลที่มีชื่อแต่ละรายการในโปรเจ็กต์ ซึ่งหมายความว่าหากคุณสร้างฐานข้อมูลหลายรายการ คุณจะต้องจัดการและใช้กฎสำหรับฐานข้อมูลแต่ละรายการแยกกัน ดูวิธีการโดยละเอียดในการใช้การอัปเดตได้ที่ใช้การอัปเดต
กฎการอ่าน/เขียนพื้นฐาน
กฎพื้นฐานประกอบด้วยคำสั่ง 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 ทั้งหมดควรชี้ไปยังเอกสาร ไม่ใช่คอลเล็กชัน คำสั่ง match สามารถชี้ไปยังเอกสารที่เฉพาะเจาะจงได้ เช่น match /cities/SF หรือใช้ไวลด์การ์ดเพื่อชี้ไปยังเอกสารใดก็ได้ในเส้นทางที่ระบุ เช่น match /cities/{city}
ในตัวอย่างข้างต้น คำสั่ง match ใช้ไวยากรณ์ไวลด์การ์ด {city}
ซึ่งหมายความว่ากฎนี้ใช้ได้กับเอกสารใดก็ได้ในคอลเล็กชัน cities เช่น
/cities/SF หรือ /cities/NYC เมื่อมีการประเมินนิพจน์ allow ในคำสั่ง match ตัวแปร 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 และคอลเล็กชันย่อย
ไวลด์การ์ดแบบเรียกซ้ำต้องอยู่ที่ส่วนท้ายของคำสั่ง match
เวอร์ชัน 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 รายการต่อคำสั่ง match แต่ในเวอร์ชัน 2 คุณสามารถวางไวลด์การ์ดนี้ไว้ที่ใดก็ได้ในคำสั่ง match เช่น
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 ที่ซ้อนทับกัน
เอกสารอาจตรงกับคำสั่ง 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 เสมอ แม้ว่ากฎแรกจะเป็น false เสมอก็ตาม
ขีดจำกัดของกฎความปลอดภัย
เมื่อทำงานกับกฎความปลอดภัย โปรดทราบขีดจำกัดต่อไปนี้
| ขีดจำกัด | รายละเอียด |
|---|---|
จำนวนการเรียก exists(), get() และ getAfter() สูงสุดต่อคำขอ |
การเกินขีดจำกัดใดขีดจำกัดหนึ่งจะทำให้เกิดข้อผิดพลาด "สิทธิ์ถูกปฏิเสธ" การเรียกการเข้าถึงเอกสารบางรายการอาจได้รับการแคช และการเรียกที่แคชไว้จะไม่นับรวมในขีดจำกัด |
ความลึกสูงสุดของคำสั่ง match ที่ซ้อนกัน |
10 |
ความยาวเส้นทางสูงสุดในส่วนเส้นทางที่อนุญาตภายในชุดคำสั่งที่ซ้อนกัน
match |
100 |
จำนวนตัวแปรการจับเส้นทางสูงสุดที่อนุญาตภายในชุดของ
คำสั่ง match ที่ซ้อนกัน |
20 |
| ความลึกสูงสุดของการเรียกใช้ฟังก์ชัน | 20 |
| จำนวนอาร์กิวเมนต์ของฟังก์ชันสูงสุด | 7 |
จำนวนการผูกตัวแปร let สูงสุดต่อฟังก์ชัน |
10 |
| จำนวนการเรียกใช้ฟังก์ชันแบบเรียกซ้ำหรือแบบวนรอบสูงสุด | 0 (ไม่อนุญาต) |
| จำนวนนิพจน์สูงสุดที่ประเมินต่อคำขอ | 1,000 |
| ขนาดสูงสุดของชุดกฎ | ชุดกฎต้องเป็นไปตามขีดจำกัดขนาด 2 รายการต่อไปนี้
|
ขั้นตอนถัดไป
- เขียนเงื่อนไขกฎความปลอดภัยที่กำหนดเอง
- อ่านข้อมูลอ้างอิงกฎความปลอดภัย