คู่มือนี้สร้างจากการ เรียนรู้ไวยากรณ์หลักของ คู่มือ ภาษากฎความปลอดภัย Firebase เพื่อแสดงวิธีเพิ่มเงื่อนไขให้กับกฎความปลอดภัย Firebase สำหรับ Cloud Storage
Building Block หลักของกฎความปลอดภัยของ Cloud Storage คือ เงื่อนไข เงื่อนไขคือนิพจน์บูลีนที่กำหนดว่าควรอนุญาตหรือปฏิเสธการดำเนินการเฉพาะ สำหรับกฎพื้นฐานการใช้ตัวอักษร true
และ false
เนื่องจากเงื่อนไขทำงานได้ดีในระดับจังหวัด แต่กฎความปลอดภัยของ Firebase สำหรับภาษา Cloud Storage ช่วยให้คุณสามารถเขียนเงื่อนไขที่ซับซ้อนมากขึ้นซึ่งสามารถ:
- ตรวจสอบการรับรองความถูกต้องของผู้ใช้
- ตรวจสอบข้อมูลขาเข้า
การรับรองความถูกต้อง
กฎความปลอดภัยของ Firebase สำหรับ Cloud Storage ผสานรวมกับ Firebase Authentication เพื่อมอบการตรวจสอบสิทธิ์ตามผู้ใช้ที่มีประสิทธิภาพไปยัง Cloud Storage ซึ่งช่วยให้สามารถควบคุมการเข้าถึงแบบละเอียดตามการอ้างสิทธิ์ของโทเค็นการตรวจสอบสิทธิ์ Firebase
เมื่อผู้ใช้ที่ตรวจสอบสิทธิ์ดำเนินการร้องขอกับ 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; }
กลุ่มส่วนตัว
อีกกรณีการใช้งานทั่วไปที่เท่าเทียมกันคือการอนุญาตการอนุญาตกลุ่มบนวัตถุเช่นการอนุญาตให้สมาชิกในทีมหลายคนทำงานร่วมกันในเอกสารที่แชร์ มีหลายวิธีในการดำเนินการนี้:
- สร้างโทเค็นที่กำหนดเองของ Firebase Authentication ที่มีข้อมูลเพิ่มเติมเกี่ยวกับสมาชิกกลุ่ม (เช่น ID กลุ่ม)
- รวมข้อมูลกลุ่ม (เช่น ID กลุ่มหรือรายการ
uid
ได้รับอนุญาต) ใน ข้อมูลเมตาของไฟล์
เมื่อข้อมูลนี้ถูกเก็บไว้ในโทเค็นหรือข้อมูลเมตาของไฟล์แล้วสามารถอ้างอิงได้จากภายในกฎ:
// 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 นอกเหนือจาก ID เฉพาะของผู้ใช้และเพย์โหลดการตรวจสอบสิทธิ์ Firebase ในออบเจ็กต์ request.auth
ตามที่อธิบายไว้ข้างต้นตัวแปร request
มีเส้นทางไฟล์ที่กำลังดำเนินการร้องขอเวลาที่ได้รับคำขอและค่า resource
ใหม่หาก คำขอคือการเขียน นอกจากนี้ยังมีส่วนหัว HTTP และสถานะการพิสูจน์ตัวตน
ออบเจ็กต์ request
ยังมี ID เฉพาะของผู้ใช้และเพย์โหลดการตรวจสอบสิทธิ์ Firebase ในออบเจ็กต์ request.auth
ซึ่งจะอธิบายเพิ่มเติมในส่วน ความปลอดภัย ของผู้ใช้ของเอกสาร
รายการคุณสมบัติทั้งหมดในออบเจ็กต์ request
มีอยู่ด้านล่าง:
ทรัพย์สิน | ประเภท | คำอธิบาย |
---|---|---|
auth | แมป <string, string> | เมื่อผู้ใช้เข้าสู่ระบบให้ระบุ uid รหัสเฉพาะของผู้ใช้และ token แผนที่ของการอ้างสิทธิ์ JWT การตรวจสอบสิทธิ์ Firebase มิฉะนั้นจะเป็น null |
params | แมป <string, string> | แผนที่ที่มีพารามิเตอร์การสืบค้นของคำขอ |
path | เส้นทาง | path แสดงพา ธ ที่ร้องขอกำลังดำเนินการที่ |
resource | แมป <string, string> | ค่าทรัพยากรใหม่แสดงเฉพาะในคำขอ write |
time | การประทับเวลา | การประทับเวลาที่แสดงเวลาของเซิร์ฟเวอร์ที่คำขอได้รับการประเมินที่ |
การประเมินทรัพยากร
เมื่อประเมินกฎคุณอาจต้องการประเมินข้อมูลเมตาของไฟล์ที่กำลังอัปโหลดดาวน์โหลดแก้ไขหรือลบ วิธีนี้ช่วยให้คุณสามารถสร้างกฎที่ซับซ้อนและมีประสิทธิภาพซึ่งทำสิ่งต่างๆเช่นอนุญาตให้อัปโหลดเฉพาะไฟล์ที่มีเนื้อหาบางประเภทหรือเฉพาะไฟล์ที่มีขนาดใหญ่กว่าขนาดที่กำหนดเท่านั้นที่จะลบได้
กฎความปลอดภัยของ Firebase สำหรับ Cloud Storage ให้ข้อมูลเมตาของไฟล์ในออบเจ็กต์ resource
ซึ่งมีคู่คีย์ / ค่าของข้อมูลเมตาที่ปรากฏในวัตถุ Cloud Storage คุณสมบัติเหล่านี้สามารถตรวจสอบได้ในคำขอ read
หรือ write
เพื่อให้แน่ใจว่าข้อมูลมีความสมบูรณ์
ในการร้องขอการ write
(เช่นการอัปโหลดการอัปเดตข้อมูลเมตาและการลบ) นอกเหนือจากออบเจ็กต์ resource
ซึ่งมีข้อมูลเมตาของไฟล์สำหรับไฟล์ที่มีอยู่ในเส้นทางคำขอแล้วคุณยังสามารถใช้วัตถุ request.resource
ซึ่งมีชุดย่อยของข้อมูลเมตาของไฟล์ที่จะเขียนหากอนุญาตให้เขียนได้ คุณสามารถใช้ค่าทั้งสองนี้เพื่อรับรองความสมบูรณ์ของข้อมูลหรือบังคับใช้ข้อ จำกัด ของแอปพลิเคชันเช่นประเภทไฟล์หรือขนาด
รายการคุณสมบัติทั้งหมดในวัตถุ resource
มีอยู่ด้านล่าง:
ทรัพย์สิน | ประเภท | คำอธิบาย |
---|---|---|
name | สตริง | ชื่อเต็มของวัตถุ |
bucket | สตริง | ชื่อของที่เก็บข้อมูลออบเจ็กต์นี้อยู่ |
generation | int | การ สร้างวัตถุ Google Cloud Storage ของออบเจ็กต์นี้ |
metageneration | int | การสร้าง ออบเจ็กต์ Google Cloud Storage ของออบเจ็กต์นี้ |
size | int | ขนาดของวัตถุเป็นไบต์ |
timeCreated | การประทับเวลา | การประทับเวลาแทนเวลาที่สร้างวัตถุ |
updated | การประทับเวลา | การประทับเวลาแสดงเวลาที่อัปเดตวัตถุครั้งล่าสุด |
md5Hash | สตริง | แฮช MD5 ของวัตถุ |
crc32c | สตริง | แฮช crc32c ของวัตถุ |
etag | สตริง | etag ที่เกี่ยวข้องกับวัตถุนี้ |
contentDisposition | สตริง | การจัดการเนื้อหาที่เกี่ยวข้องกับออบเจ็กต์นี้ |
contentEncoding | สตริง | การเข้ารหัสเนื้อหาที่เกี่ยวข้องกับอ็อบเจ็กต์นี้ |
contentLanguage | สตริง | ภาษาของเนื้อหาที่เกี่ยวข้องกับอ็อบเจ็กต์นี้ |
contentType | สตริง | ประเภทเนื้อหาที่เกี่ยวข้องกับออบเจ็กต์นี้ |
metadata | แมป <string, string> | คู่คีย์ / ค่าของข้อมูลเมตาที่กำหนดเองเพิ่มเติมที่นักพัฒนาระบุไว้ |
request.resource
มีสิ่งเหล่านี้ทั้งหมดยกเว้น generation
, metageneration
, etag
, timeCreated
และ updated
ตรวจสอบข้อมูล
นอกจากนี้ยังสามารถใช้กฎความปลอดภัย Firebase สำหรับ 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 ของคุณมีความซับซ้อนมากขึ้นคุณอาจต้องการรวมชุดเงื่อนไขในฟังก์ชันที่คุณสามารถใช้ซ้ำได้ในชุดกฎของคุณ กฎความปลอดภัยรองรับฟังก์ชันที่กำหนดเอง ไวยากรณ์สำหรับฟังก์ชันที่กำหนดเองจะคล้าย JavaScript เล็กน้อย แต่ฟังก์ชันกฎความปลอดภัยของ Firebase จะเขียนด้วยภาษาเฉพาะโดเมนซึ่งมีข้อ จำกัด ที่สำคัญบางประการ:
- ฟังก์ชันสามารถมีคำสั่ง
return
เพียงรายการเดียว พวกเขาไม่สามารถมีตรรกะเพิ่มเติมใด ๆ ตัวอย่างเช่นไม่สามารถดำเนินการลูปหรือเรียกใช้บริการภายนอกได้ - ฟังก์ชันสามารถเข้าถึงฟังก์ชันและตัวแปรโดยอัตโนมัติจากขอบเขตที่กำหนดไว้ ตัวอย่างเช่นฟังก์ชันที่กำหนดภายในขอบเขตของ
service firebase.storage
มีสิทธิ์เข้าถึงตัวแปรresource
และสำหรับ Cloud Firestore เท่านั้นฟังก์ชันในตัวเช่นget()
และexists()
- ฟังก์ชันอาจเรียกใช้ฟังก์ชันอื่น ๆ แต่อาจไม่เรียกคืน ความลึกสแต็กการโทรทั้งหมด จำกัด ไว้ที่ 10
- ในเวอร์ชัน
rules2
ฟังก์ชันสามารถกำหนดตัวแปรโดยใช้คีย์เวิร์ดlet
ฟังก์ชั่นสามารถมีการผูกแบบ let จำนวนเท่าใดก็ได้ แต่ต้องลงท้ายด้วยคำสั่ง return
ฟังก์ชันถูกกำหนดด้วยคีย์เวิร์ดของ function
และรับอาร์กิวเมนต์เป็นศูนย์หรือมากกว่า ตัวอย่างเช่นคุณอาจต้องการรวมเงื่อนไขสองประเภทที่ใช้ในตัวอย่างด้านบนเป็นฟังก์ชันเดียว:
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 ทำให้สามารถดูแลรักษาได้มากขึ้นเมื่อความซับซ้อนของกฎเพิ่มขึ้น
ขั้นตอนถัดไป
หลังจากการอภิปรายเงื่อนไขนี้คุณมีความเข้าใจที่ซับซ้อนมากขึ้นเกี่ยวกับกฎและพร้อมที่จะ:
เรียนรู้วิธีจัดการกรณีการใช้งานหลักและเรียนรู้ขั้นตอนการทำงานสำหรับการพัฒนาทดสอบและปรับใช้กฎ:
- เขียนกฎที่กล่าวถึง สถานการณ์ทั่วไป
- สร้างความรู้ของคุณโดยทบทวนสถานการณ์ที่คุณต้อง มองเห็นและหลีกเลี่ยงกฎที่ไม่ปลอดภัย
- ตรวจสอบวิธีการที่ใช้ได้สำหรับการ ปรับใช้กฎ