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

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

องค์ประกอบที่ใช้สร้างสรรค์หลักของ Cloud Storage Security Rules คือเงื่อนไข ต คือนิพจน์บูลีนที่กำหนดว่าการดำเนินการหนึ่งๆ หรือไม่ ควรยอมรับหรือปฏิเสธ สำหรับกฎพื้นฐาน ให้ใช้ true และ false ลิเทอรัล เนื่องจากสภาวะต่างๆ ทำงานได้ดี แต่รูปแบบ Firebase Security Rules for 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;
}

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

Use Case ที่พบบ่อยที่สุดสำหรับ 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 map<string, string> คู่คีย์/ค่าของข้อมูลเมตาที่กำหนดเองเพิ่มเติมที่นักพัฒนาซอฟต์แวร์ระบุ

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() คุณต้องหลีกตัวแปรอย่างชัดเจนโดยใช้ไวยากรณ์ $(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 จะช่วยให้ดูแลรักษาได้ง่ายขึ้นเมื่อกฎมีความซับซ้อนมากขึ้น

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

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

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