Google 致力于为黑人社区推动种族平等。查看具体举措
此页面由 Cloud Translation API 翻译。
Switch to English

Firebase Cloud Storage安全规则中的使用条件

本指南以学习《 Firebase安全规则》语言指南的核心语法为基础,以显示如何向您的Firebase Cloud Storage安全规则添加条件。

条件是云存储安全规则的主要构建块。条件是一个布尔表达式,它确定是应允许还是拒绝特定的操作。对于基本规则,使用truefalse文字作为条件非常有效。但是,《 Firebase Cloud Storage安全规则》语言为您提供了编写更复杂条件的方法,这些条件可以:

  • 检查用户身份验证
  • 验证传入数据

验证

《用于Cloud Storage的Firebase安全规则》与Firebase身份验证集成,可为Cloud Storage提供基于用户的强大身份验证。这允许基于Firebase身份验证令牌的声明进行粒度访问控制。

当已验证的用户执行对云存储的请求,则request.auth可变填充与用户的uidrequest.auth.uid )以及火力地堡认证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身份验证自定义令牌,其中包含有关组成员的其他信息(例如组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;
}

要求评估

使用发送到Cloud Storage的request评估上传,下载,元数据更改和删除。除了如上所述的request.auth对象中的用户唯一ID和Firebase身份验证有效负载外, request变量还包含正在执行请求的文件路径,接收请求的时间以及新resource值(如果有)该请求是写操作。 HTTP标头和身份验证状态也包括在内。

request对象在request.auth对象中还包含用户的唯一ID和Firebase身份验证有效负载,这将在文档的“基于用户的安全性”部分中进一步说明。

以下是request对象中属性的完整列表:

财产类型描述
auth map <字串,字串>当用户登录时,提供uid ,用户的唯一ID和token ,即Firebase身份验证JWT声明的映射。否则,它将为null
params map <字串,字串>包含请求查询参数的映射。
path小路代表正在执行请求的path的路径。
resource map <字串,字串>新资源值,仅在write请求中出现。
time时间戳记表示请求评估所在的服务器时间的时间戳。

资源评估

在评估规则时,您可能还需要评估正在上传,下载,修改或删除的文件的元数据。这使您可以创建复杂且功能强大的规则,这些规则的作用类似于仅允许上传具有某些内容类型的文件,或仅删除大于特定大小的文件。

《用于云存储的Firebase安全规则》在resource对象中提供文件元数据,该文件元数据包含浮在云存储对象中的元数据的键/值对。可以根据readwrite请求检查这些属性,以确保数据完整性。

write请求(例如上载,元数据更新和删除)上,除了resource对象(其中包含请求路径中当前存在的文件的文件元数据)之外,您还可以使用request.resource对象,如果允许写入,则它包含要写入的文件元数据的子集。您可以使用这两个值来确保数据完整性或强制执行应用程序约束,例如文件类型或大小。

下面提供了resource对象中属性的完整列表:

财产类型描述
name细绳对象的全名
bucket细绳该对象所在的存储桶的名称。
generation整型对象Google Cloud Storage对象生成
metageneration整型对象Google Cloud Storage对象元生成。
size整型对象的大小(以字节为单位)。
timeCreated时间戳记表示对象创建时间的时间戳。
updated时间戳记表示对象上次更新时间的时间戳。
md5Hash细绳对象的MD5哈希值。
crc32c细绳对象的crc32c哈希。
etag细绳与此对象关联的etag。
contentDisposition细绳与此对象关联的内容处置。
contentEncoding细绳与此对象关联的内容编码。
contentLanguage细绳与此对象关联的内容语言。
contentType细绳与此对象关联的内容类型。
metadata map <字串,字串>开发人员指定的其他自定义元数据的键/值对。

request.resource包含了所有这些与外generationmetagenerationetagtimeCreatedupdated

验证数据

Firebase Cloud Storage安全规则还可以用于数据验证,包括验证文件名和路径以及文件元数据属性,例如contentTypesize

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安全规则中使用功能可以使它们随着规则的复杂性的提高而更加易于维护。

下一步

在讨论条件之后,您将对规则有更深入的了解,并准备:

了解如何处理核心用例,并了解用于开发,测试和部署规则的工作流: