获取我们在 Firebase 峰会上发布的所有信息,了解 Firebase 可如何帮助您加快应用开发速度并满怀信心地运行应用。了解详情

构建 Cloud Firestore 安全规则

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

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变量将解析为城市文档名称,例如SFNYC

细化操作

在某些情况下,将readwrite分解为更细粒度的操作很有用。例如,您的应用程序可能希望对文档创建和文档删除执行不同的条件。或者您可能希望允许单个文档读取但拒绝大型查询。

read规则可以分为getlist ,而write规则可以分为createupdatedelete

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()调用的最大次数
  • 10 用于单文档请求和查询请求。
  • 20 用于多文档读取、事务和批量写入。之前的 10 个限制也适用于每个操作。

    例如,假设您创建了一个包含 3 个写入操作的批处理写入请求,并且您的安全规则使用 2 个文档访问调用来验证每个写入。在这种情况下,每个写入使用其 10 个访问调用中的 2 个,而批处理的写入请求使用其 20 个访问调用中的 6 个。

超过任一限制都会导致权限被拒绝错误。

某些文档访问调用可能会被缓存,缓存的调用不计入限制。

最大嵌套match语句深度10
一组嵌套match语句中允许的最大路径长度(以路径段为单位) 100
一组嵌套match语句中允许的最大路径捕获变量数20
最大函数调用深度20
函数参数的最大数量7
每个函数的最大let变量绑定数10
递归或循环函数调用的最大次数0(不允许)
每个请求评估的最大表达式数1,000
规则集的最大大小规则集必须遵守两个大小限制:
  • 从 Firebase 控制台或使用firebase deploy从 CLI 发布的规则集文本源的大小限制为 256 KB。
  • 当 Firebase 处理源代码并使其在后端处于活动状态时,编译规则集的大小限制为 250 KB。

下一步