ใช้เงื่อนไขในกฎการรักษาความปลอดภัยของ Firebase Cloud Storage

คู่มือนี้สร้างขึ้นจากเรียนรู้ไวยากรณ์หลักของคู่มือภาษาFirebase Security Rules เพื่อแสดงวิธีเพิ่มเงื่อนไขลงใน Firebase Security Rules สำหรับ Cloud Storage

องค์ประกอบที่ใช้สร้างสรรค์หลักของ Cloud Storage Security Rules คือเงื่อนไข ต คือนิพจน์บูลีนที่กำหนดว่าการดำเนินการหนึ่งๆ หรือไม่ ควรยอมรับหรือปฏิเสธ สำหรับกฎพื้นฐาน ให้ใช้ true และ false ลิเทอรัล เนื่องจากสภาวะต่างๆ ทำงานได้ดี แต่ Firebase Security Rules สำหรับ Cloud Storage ภาษาช่วยให้คุณเขียนเงื่อนไขที่ซับซ้อนขึ้น ซึ่งสามารถ

  • ตรวจสอบการตรวจสอบสิทธิ์ผู้ใช้
  • ตรวจสอบข้อมูลขาเข้า

การตรวจสอบสิทธิ์

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

เมื่อผู้ใช้ที่ตรวจสอบสิทธิ์แล้วส่งคำขอกับ Cloud Storage ระบบจะเติมตัวแปร request.auth ด้วย uid ของผู้ใช้ (request.auth.uid) รวมถึงคำกล่าวอ้างของ Firebase Authentication JWT (request.auth.token)

นอกจากนี้ เมื่อใช้การตรวจสอบสิทธิ์ที่กำหนดเอง การอ้างสิทธิ์เพิ่มเติมจะปรากฏขึ้น ในช่อง request.auth.token

เมื่อผู้ใช้ที่ไม่ได้รับการตรวจสอบสิทธิ์ส่งคำขอ ตัวแปร request.auth จะเป็น null

การใช้ข้อมูลนี้ทำให้มีวิธีทั่วไปหลายวิธีในการใช้การตรวจสอบสิทธิ์เพื่อรักษาความปลอดภัย ไฟล์:

  • สาธารณะ: ละเว้น request.auth
  • ตรวจสอบสิทธิ์แบบส่วนตัวแล้ว: ตรวจสอบว่า request.auth ไม่ใช่ null
  • ส่วนตัวของผู้ใช้: ตรวจสอบว่า request.auth.uid เท่ากับเส้นทาง uid
  • กลุ่มส่วนตัว: ตรวจสอบการอ้างสิทธิ์ของโทเค็นที่กำหนดเองเพื่อให้ตรงกับการอ้างสิทธิ์ที่เลือก หรือ อ่านข้อมูลเมตาของไฟล์เพื่อดูว่ามีช่องข้อมูลเมตาหรือไม่

สาธารณะ

กฎใดก็ตามที่ไม่พิจารณาบริบท request.auth อาจถือเป็น public เนื่องจากไม่พิจารณาบริบทการตรวจสอบสิทธิ์ของผู้ใช้ กฎเหล่านี้อาจเป็นประโยชน์ในการแสดงข้อมูลสาธารณะ เช่น เนื้อหาเกม เสียง หรือเนื้อหาแบบคงที่อื่นๆ

// Anyone to read a public image if the file is less than 100kB
// Anyone can upload a public file ending in '.txt'
match /public/{imageId} {
  allow read: if resource.size < 100 * 1024;
  allow write: if imageId.matches(".*\\.txt");
}

ความเป็นส่วนตัวที่ตรวจสอบสิทธิ์แล้ว

ในบางกรณี คุณอาจต้องการให้ผู้ใช้ที่ได้รับการตรวจสอบสิทธิ์ทั้งหมดของ แอปพลิเคชันของคุณ แต่ไม่ใช่โดยผู้ใช้ที่ไม่ได้รับการตรวจสอบสิทธิ์ นับตั้งแต่วันที่ request.auth คือ null สำหรับผู้ใช้ที่ไม่ได้รับการตรวจสอบสิทธิ์ทั้งหมด คุณเพียงแค่ทำเครื่องหมาย มีตัวแปร request.auth อยู่เพื่อให้ต้องมีการตรวจสอบสิทธิ์

// Require authentication on all internal image reads
match /internal/{imageId} {
  allow read: if request.auth != null;
}

ส่วนตัวของผู้ใช้

โดยทั่วไปกรณีการใช้งาน request.auth ที่พบบ่อยที่สุดคือการให้ ผู้ใช้ที่มีสิทธิ์แบบละเอียดในไฟล์: ตั้งแต่การอัปโหลดรูปโปรไฟล์ การอ่านเอกสารส่วนตัว

เนื่องจากไฟล์ใน Cloud Storage มี "เส้นทาง" แบบเต็ม ไฟล์ก็ต้องใช้ เพื่อทำให้ไฟล์ที่ผู้ใช้ควบคุมคือส่วนที่ไม่ซ้ำกันที่ระบุตัวผู้ใช้ ในคำนำหน้าชื่อไฟล์ (เช่น uid ของผู้ใช้) ซึ่งสามารถ เลือกเมื่อมีการประเมินกฎ:

// Only a user can upload their profile picture, but anyone can view it
match /users/{userId}/profilePicture.png {
  allow read;
  allow write: if request.auth.uid == userId;
}

กลุ่มส่วนตัว

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

เมื่อเก็บข้อมูลนี้ไว้ในโทเค็นหรือข้อมูลเมตาของไฟล์แล้ว ก็จะนำไปอ้างอิงได้ จากภายในกฎ:

// Allow reads if the group ID in your token matches the file metadata's `owner` property
// Allow writes if the group ID is in the user's custom token
match /files/{groupId}/{fileName} {
  allow read: if resource.metadata.owner == request.auth.token.groupId;
  allow write: if request.auth.token.groupId == groupId;
}

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

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

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

รายการที่พักทั้งหมดในออบเจ็กต์ request แสดงอยู่ด้านล่าง

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

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

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

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

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

รายการที่พักทั้งหมดในออบเจ็กต์ resource แสดงอยู่ด้านล่าง

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

request.resource มีข้อมูลทั้งหมดนี้ ยกเว้น generation metageneration, etag, timeCreated และ updated

ปรับปรุงด้วย Cloud Firestore

คุณเข้าถึงเอกสารใน Cloud Firestore เพื่อประเมินการให้สิทธิ์อื่นๆ ได้ เกณฑ์

การใช้ฟังก์ชัน firestore.get() และ firestore.exists() ทำให้การรักษาความปลอดภัย กฎสามารถประเมินคำขอที่เข้ามาโดยเปรียบเทียบกับเอกสารใน Cloud Firestore ทั้งฟังก์ชัน firestore.get() และ firestore.exists() ต้องการอย่างสมบูรณ์ เส้นทางเอกสารที่ระบุ เมื่อใช้ตัวแปรเพื่อสร้างเส้นทางสำหรับ firestore.get() และ firestore.exists() คุณต้อง Escape อย่างชัดเจน โดยใช้ไวยากรณ์ $(variable)

ในตัวอย่างด้านล่าง เราจะเห็นกฎที่จำกัดการเข้าถึงในการอ่านไฟล์สำหรับ ผู้ใช้ที่เป็นสมาชิกของสโมสรที่เฉพาะเจาะจง

service firebase.storage {
  match /b/{bucket}/o {
    match /users/{club}/files/{fileId} {
      allow read: if club in
        firestore.get(/databases/(default)/documents/users/$(request.auth.id)).memberships
    }
  }
}
ในตัวอย่างถัดไป เฉพาะเพื่อนของผู้ใช้เท่านั้นที่จะเห็นภาพถ่าย
service firebase.storage {
  match /b/{bucket}/o {
    match /users/{userId}/photos/{fileId} {
      allow read: if
        firestore.exists(/databases/(default)/documents/users/$(userId)/friends/$(request.auth.id))
    }
  }
}

เมื่อคุณสร้างและบันทึก Cloud Storage Security Rules รายการแรกที่ใช้ Cloud Firestore เหล่านี้ คุณจะได้รับข้อความแจ้งในคอนโซล Firebase หรือ Firebase CLI ให้ เปิดใช้สิทธิ์เพื่อเชื่อมต่อผลิตภัณฑ์ทั้งสอง

คุณสามารถปิดใช้ฟีเจอร์นี้ได้โดยการนำบทบาท IAM ออก ดังที่อธิบายไว้ใน จัดการและทำให้ Firebase Security Rules ใช้งานได้

ตรวจสอบข้อมูล

Firebase Security Rules สําหรับ Cloud Storage ยังใช้สําหรับการตรวจสอบข้อมูลได้อีกด้วย ซึ่งได้แก่ การตรวจสอบชื่อและเส้นทางของไฟล์ รวมถึงคุณสมบัติข้อมูลเมตาของไฟล์ contentType และ size

service firebase.storage {
  match /b/{bucket}/o {
    match /images/{imageId} {
      // Only allow uploads of any image file that's less than 5MB
      allow write: if request.resource.size < 5 * 1024 * 1024
                   && request.resource.contentType.matches('image/.*');
    }
  }
}

ฟังก์ชันที่กำหนดเอง

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

  • ฟังก์ชันจะมีคำสั่ง return ได้เพียงคำสั่งเดียว จึงไม่สามารถ มีตรรกะเพิ่มเติม เช่น ไม่สามารถเรียกใช้ลูปได้ หรือโทรหาบริการภายนอก
  • ฟังก์ชันจะเข้าถึงฟังก์ชันและตัวแปรจากขอบเขตได้โดยอัตโนมัติ ตามที่มีการกำหนดไว้ ตัวอย่างเช่น ฟังก์ชันที่กำหนดภายใน ขอบเขต service firebase.storage มีสิทธิ์เข้าถึง ตัวแปร resource และฟังก์ชันในตัวสำหรับ Cloud Firestore เท่านั้น เช่น get() และ exists()
  • ฟังก์ชันต่างๆ อาจเรียกใช้ฟังก์ชันอื่นๆ แต่อาจไม่แสดงใหม่ การโทรทั้งหมด จำกัดความลึกของสแต็กไว้ที่ 10
  • ในเวอร์ชัน rules2 ฟังก์ชันจะกำหนดตัวแปรโดยใช้คีย์เวิร์ด let ได้ ฟังก์ชันมีการเชื่อมโยง Let ๆ กี่รายการก็ได้ แต่ต้องลงท้ายด้วยการส่งกลับ ข้อความ

ระบบจะกำหนดฟังก์ชันด้วยคีย์เวิร์ด function และใช้เวลา 0 ขึ้นไป อาร์กิวเมนต์ เช่น คุณอาจต้องการรวมเงื่อนไข 2 ประเภทที่ใช้รวมกัน ในตัวอย่างข้างต้นให้เป็นฟังก์ชันเดียว

service firebase.storage {
  match /b/{bucket}/o {
    // True if the user is signed in or the requested data is 'public'
    function signedInOrPublic() {
      return request.auth.uid != null || resource.data.visibility == 'public';
    }
    match /images/{imageId} {
      allow read, write: if signedInOrPublic();
    }
    match /mp3s/{mp3Ids} {
      allow read: if signedInOrPublic();
    }
  }
}

การใช้ฟังก์ชันใน Firebase Security Rules จะทำให้บำรุงรักษาได้มากขึ้นเนื่องจากมีความซับซ้อน กฎก็ใหญ่ขึ้น

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

หลังจากปรึกษาหารือเกี่ยวกับเงื่อนไขกันแล้ว คุณมีทางเลือกมากขึ้น เข้าใจกฎต่าง ๆ และพร้อมที่จะ:

เรียนรู้วิธีจัดการกรณีการใช้งานหลักและเรียนรู้เวิร์กโฟลว์สำหรับการพัฒนา การทดสอบและการใช้งานกฎ: