Firebase规则配置:仅验证指定字段并限制写入结构
Got it, let's walk through exactly how to set up your Firebase Security Rules to hit both of your requirements. I'll share concrete, tested rule snippets and break down what each part does so you can tweak it to your exact use case.
1. Validate Only Specific Fields
First, we need to ensure that any write operation only includes the fields we explicitly allow, and that those fields are the correct data type. Let's assume you want to enforce that writes to your users collection follow a strict structure: a top-level profile map (holding user contact details) and a createdAt timestamp, with no extra fields allowed.
Here's the rule snippet:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /users/{userId} { allow write: if // Only allow these exact top-level fields request.resource.data.keys().hasOnly(['profile', 'createdAt']) && // Make sure profile is a nested map with required fields request.resource.data.profile is map && request.resource.data.profile.hasAll(['email', 'phone', 'username']) && // Validate each profile field's data type request.resource.data.profile.email is string && request.resource.data.profile.phone is string && request.resource.data.profile.username is string && // Ensure createdAt is a proper timestamp request.resource.data.createdAt is timestamp; } } }
Quick Breakdown:
request.resource.data.keys().hasOnly(...): This blocks any write that includes top-level fields we didn't list—no surprise extra data gets stored.- The
profilechecks confirm that the nested map exists, contains all the user details we need, and each field is the right type (e.g.,emailmust be a string, not a number).
2. Block Direct Top-Level User Fields
Your second requirement is to prevent writing email, phone, or username directly under the users document (like User -> email). Instead, we want these fields tucked inside the profile sub-map. We can add an explicit check to reject any write that tries to put these fields at the top level.
Updated rule snippet:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /users/{userId} { allow write: if // Reject writes that have these fields at the top level !request.resource.data.keys().hasAny(['email', 'phone', 'username']) && // Enforce our allowed top-level fields only request.resource.data.keys().hasOnly(['profile', 'createdAt']) && // Validate the profile structure and its fields request.resource.data.profile is map && request.resource.data.profile.hasAll(['email', 'phone', 'username']) && request.resource.data.profile.email is string && request.resource.data.profile.phone is string && request.resource.data.profile.username is string && request.resource.data.createdAt is timestamp; } } }
Critical Check Here:
!request.resource.data.keys().hasAny(...): The exclamation mark negates the check, so if any of the forbidden top-level fields are present, the write is rejected outright. This forces all user contact details into theprofilemap as intended.
Pro Tip: Test Your Rules
Don't forget to test these rules using the Firebase Rules Playground in your Firebase Console. Try:
- A valid write with the correct structure (should be allowed)
- A write with
emailat the top level (should be blocked) - A write missing a required profile field (should be blocked)
- A write with a wrong data type (e.g.,
phoneas a number instead of string—should be blocked)
内容的提问来源于stack exchange,提问作者ManOfWar

