Cloud Firestore 安全规则允许您控制对数据库中文档和集合的访问。灵活的规则语法允许您创建匹配任何内容的规则,从对整个数据库的所有写入到对特定文档的操作。
本指南描述了安全规则的基本语法和结构。将此语法与安全规则条件相结合以创建完整的规则集。
服务和数据库声明
Cloud Firestore 安全规则始终以以下声明开头:
service cloud.firestore {
match /databases/{database}/documents {
// ...
}
}
service cloud.firestore
声明将规则的范围限定为 Cloud Firestore,防止 Cloud Firestore 安全规则与其他产品(例如 Cloud Storage)的规则发生冲突。
match /databases/{database}/documents
声明指定规则应匹配项目中的任何 Cloud Firestore 数据库。目前每个项目只有一个名为(default)
的数据库。
基本读/写规则
基本规则包括指定文档路径的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 /cities/SF
或使用通配符指向指定路径中的任何文档,如match /cities/{city}
。
在上面的示例中,匹配语句使用{city}
通配符语法。这意味着该规则适用于cities
集合中的任何文档,例如/cities/SF
或/cities/NYC
。当评估 match 语句中的allow
表达式时, 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 中,递归通配符匹配一个或多个路径项。它们不匹配空路径,因此match /cities/{city}/{document=**}
匹配子集合中的文档但不匹配cities
集合中的文档,而match /cities/{document=**}
匹配子集合中的两个文档cities
集合和子集合。
递归通配符必须出现在匹配语句的末尾。
版本 2
在安全规则的版本 2 中,递归通配符匹配零个或多个路径项。 match/cities/{city}/{document=**}
匹配任何子集合中的文档以及cities
集合中的文档。
您必须通过添加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>;
}
}
}
每个匹配语句最多可以有一个递归通配符,但在版本 2 中,您可以将此通配符放在匹配语句中的任何位置。例如:
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
语句。在多个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
集合的所有读写操作,因为第二条规则始终为true
,即使第一条规则始终为false
。
安全规则限制
在使用安全规则时,请注意以下限制:
限制 | 细节 |
---|---|
每个请求的exists() 、 get() 和getAfter() 调用的最大次数 |
超过任一限制都会导致权限被拒绝错误。 某些文档访问调用可能会被缓存,缓存的调用不计入限制。 |
最大嵌套match 语句深度 | 10 |
一组嵌套match 语句中允许的最大路径长度(以路径段为单位) | 100 |
一组嵌套match 语句中允许的最大路径捕获变量数 | 20 |
最大函数调用深度 | 20 |
函数参数的最大数量 | 7 |
每个函数的最大let 变量绑定数 | 10 |
递归或循环函数调用的最大次数 | 0(不允许) |
每个请求评估的最大表达式数 | 1,000 |
规则集的最大大小 | 规则集必须遵守两个大小限制:
|