规则:类型
。读
授予客户端对 Firebase 实时数据库位置的读取权限。
.read
规则是一种安全规则,它授予客户端对 Firebase 实时数据库位置的读取访问权限。例如:
".read": "auth != null && auth.provider == 'twitter'"
.read
规则的值是一个字符串,它被评估为 JavaScript 表达式语法的子集,并进行了一些行为更改以提高清晰度和正确性。授予读取位置权限的.read
规则也将允许读取该位置的任何后代,即使后代有自己的失败的.read
规则。
.read
规则可以访问除newData
之外的所有 Firebase 实时数据库规则变量。
。写
授予客户端对 Firebase 实时数据库位置的写入权限。
.write
规则是一种安全规则,它授予客户端对 Firebase 实时数据库位置的写入权限。例如:
".write": "auth != null && auth.token.isAdmin == true"
.write
规则的值是一个字符串,它被评估为 JavaScript 表达式语法的子集,并进行了一些行为更改以提高清晰度和正确性。授予写入位置权限的.write
规则也将允许写入该位置的任何后代,即使后代有自己的失败的.write
规则。
.write
规则可以访问 Firebase 实时数据库的所有规则变量。
。证实
在.write
规则授予访问权限后使用,以确保写入的数据符合特定架构。
一旦.write
规则授予访问权限,就会使用.validate
规则,以确保写入的数据符合特定标准。除了授予访问权限的.write
之外,所有相关的.validate
规则都必须成功才能允许写入。例如:
".validate": "newData.hasChildren(['name', 'age'])"
.validate
规则的值是一个字符串,它作为 JavaScript 表达式语法的子集进行计算,并进行一些行为更改以提高清晰度和正确性。
.validate
规则可以访问 Firebase 实时数据库的所有规则变量。
.indexOn
通过告诉 Firebase 实时数据库您希望为数据索引哪些键来提高查询性能。
.indexOn
规则告诉 Firebase 实时数据库服务器对数据中的特定键建立索引,以提高查询性能。例如,给定一个包含恐龙数据集合的数据库,我们可以通过添加以下规则告诉 Firebase 实时数据库在从服务器返回查询之前对查询进行优化:
{
"rules": {
"dinosaurs": {
".indexOn": ["height", "length"]
}
}
}
您可以通过参考安全指南中有关为数据建立索引的部分来了解有关.indexOn
规则的更多信息。
规则:变量
授权
如果客户端已通过身份验证,则包含令牌有效负载的变量;如果客户端未通过身份验证,则包含null
。
Firebase 实时数据库允许您轻松地向多个内置提供商进行身份验证,并为它们生成身份验证令牌。用户通过内置提供程序之一进行身份验证后,auth 变量将包含以下内容:
场地 | 描述 |
---|---|
provider | 使用的身份验证方法(例如“密码”、“匿名”、“facebook”、“github”、“google”或“twitter”)。 |
uid | 唯一的用户 ID,保证在所有提供商中都是唯一的。 |
token | Firebase 身份验证 ID 令牌的内容。请参阅auth.token 。 |
例如,我们可以有如下规则,允许用户创建评论,只要他们将其用户 ID 与评论一起存储即可:
{
"rules": {
".read": true,
"$comment": {
".write": "!data.exists() && newData.child('user_id').val() == auth.uid"
}
}
}
我们还可以制定如下规则,允许用户只要使用 Facebook 登录即可创建评论:
{
"rules": {
".read": true,
"$comment": {
".write": "!data.exists() && auth.provider == 'facebook'"
}
}
}
授权令牌
包含 Firebase 身份验证 ID 令牌内容的变量。
该令牌包含以下部分或全部键:
场地 | 描述 |
---|---|
email | 与帐户关联的电子邮件地址(如果存在)。 |
email_verified | 如果用户已验证他们有权访问email 地址,则为true 。一些提供商会自动验证他们拥有的电子邮件地址。 |
phone_number | 与帐户关联的电话号码(如果存在)。 |
name | 用户的显示名称(如果已设置)。 |
sub | 用户的 Firebase UID。这在项目中是独一无二的。 |
firebase.identities | 与该用户帐户关联的所有身份的字典。字典的键可以是以下任意一个: email 、 phone 、 google.com 、 facebook.com 、 github.com 、 twitter.com 。字典的值是与帐户关联的每个身份提供者的唯一标识符的数组。例如, auth.token.firebase.identities["google.com"][0] 包含与该帐户关联的第一个 Google 用户 ID。 |
firebase.sign_in_provider | 用于获取此令牌的登录提供程序。可以是以下字符串之一: custom 、 password 、 phone 、 anonymous 、 google.com 、 facebook.com 、 github.com 、 twitter.com 。 |
firebase.tenant | 与帐户关联的tenantId(如果存在)。例如tenant2-m6tyz |
如果使用自定义身份验证, auth.token
还包含开发人员指定的任何自定义声明。
所有这些值都可以在规则内使用。例如,要限制对与 gmail.com 地址关联的 Google 帐户的访问,我们可以添加规则:
{
"rules": {
".read": "auth != null",
"gmailUsers": {
"$uid": {
".write": "auth.token.email_verified == true && auth.token.email.matches(/.*@gmail.com$/)"
}
}
}
}
为了完整起见, auth.token
中还包含以下字段,但它们不太可能对规则有用。
场地 | 描述 |
---|---|
iss | 代币的发行者。 |
aud | 代币的受众。 |
auth_time | 用户上次使用接收令牌的设备通过凭证进行身份验证的时间。 |
iat | 令牌发行的时间。 |
exp | 令牌过期的时间。 |
$地点
一个变量,可用于引用先前在规则结构中使用的$location
的键。
当规则结构中有$location
时,您可以在规则表达式中使用匹配的$
变量来获取正在读取或写入的实际子项的名称。因此,假设我们希望为每个用户提供对其自己的/users/<user>
位置的读写访问权限。我们可以使用:
{
"rules": {
"users": {
"$user": {
".read": "auth.uid === $user",
".write": "auth.uid === $user"
}
}
}
}
当客户端尝试访问/users/barney
时, $user
默认位置将与$user
等于“barney”匹配。因此.read
规则将检查auth.uid === 'barney'
是否。因此,只有当客户端通过 uid 为“barney”进行身份验证时,读取
才会成功。/users/barney
现在
根据 Firebase 实时数据库服务器,包含自 Unix 纪元以来的毫秒数。
now
变量包含根据 Firebase 实时数据库服务器的 UNIX 纪元以来的毫秒数。例如,您可以使用它来验证用户的created
时间从未设置为将来的时间:
{
"rules": {
"users": {
"$user": {
"created": {
".validate": "newData.val() < now"
}
}
}
}
}
根
与 Firebase 实时数据库根目录中的当前数据相对应的RuleDataSnapshot 。
root 变量为您提供与 Firebase 实时数据库根目录中的当前数据相对应的RuleDataSnapshot 。您可以使用它来读取规则表达式中数据库中的任何数据。例如,如果我们希望仅当用户的/users/<id>/active
设置为 true 时才允许用户读取/comments
,我们可以使用:
{
"rules": {
"comments": {
".read": "root.child('users').child(auth.uid).child('active').val() == true"
}
}
}
然后,如果/users/barney/active
包含值 true,则使用 uid 为“barney”进行身份验证的用户可以写入/comments
节点。
数据
与 Firebase 实时数据库中当前执行规则位置的当前数据相对应的RuleDataSnapshot 。
data 变量为您提供与当前执行规则的数据库位置中的当前数据相对应的RuleDataSnapshot (与 root 不同,root 为您提供数据库根的数据)。
例如,如果您想让任何客户端访问/users/<user>
(如果/users/<user>/public
设置为 true),您可以使用:
{
"rules": {
"users": {
"$user": {
".read": "data.child('public').val() == true"
}
}
}
}
data 变量在.read
、 .write
和.validate
规则中可用。
新数据
与允许写入时生成的数据相对应的RuleDataSnapshot 。
对于.write
和.validate
规则,newData 变量为您提供一个与允许写入时将产生的数据相对应的RuleDataSnapshot (它是现有数据与正在写入的新数据的“合并”)。因此,如果您想确保每个用户都有姓名和年龄,您可以使用:
{
"rules": {
"users": {
"$user": {
".read": true,
".write": true,
".validate": "newData.hasChildren(['name', 'age'])"
}
}
}
}
由于 newData 合并了现有数据和新数据,因此即使对于“部分”更新,它也能正常运行。例如:
var fredRef = firebase.database().ref("users/fred");
// Valid since we have a name and age.
fredRef.set({ name: "Fred", age: 19 });
// Valid since we are updating the name but there's already an age.
fredRef.child("age").set(27);
// Invalid since the .validate rule will no longer be true.
fredRef.child("name").remove();
newData 变量在.read
规则中不可用,因为没有写入新数据。你应该只使用数据。
RuleDataSnapshot:方法
值()
从此RuleDataSnapshot获取原始值( string
、 number
、 boolean
或null
)。
返回值: ( String
、 Number
、 Boolean
、 Null
) - 此RuleDataSnapshot中的原始值。
与DataSnapshot.val()
不同,在具有子数据的 RuleDataSnapshot 上调用val()
将不会返回包含子数据的对象。相反,它将返回一个特殊的哨兵值。这确保了规则始终能够非常有效地运行。
因此,您必须始终使用child()
来访问子级(例如data.child('name').val()
,而不是data.val().name
)。
仅当 isReadable 子项在正在读取的位置设置为 true 时,此示例才允许读取。
".read": "data.child('isReadable').val() == true"
孩子()
获取指定相对路径位置的RuleDataSnapshot 。
参数: childPath
String
- 子数据位置的相对路径。
返回值: RuleDataSnapshot
- 子位置的RuleDataSnapshot 。
相对路径可以是简单的子名称(例如“fred”),也可以是更深的斜杠分隔路径(例如“fred/name/first”)。如果子位置没有数据,则返回空的 RuleDataSnapshot。
仅当 isReadable 子项在正在读取的位置设置为 true 时,此示例才允许读取。
".read": "data.child('isReadable').val() == true"
父级()
获取父位置的RuleDataSnapshot 。
返回值: RuleDataSnapshot
- 父位置的RuleDataSnapshot 。
如果此实例引用 Firebase 实时数据库的根,则它没有父级, parent()
将失败,导致当前规则表达式被跳过(作为失败)。
仅当 isReadable 同级设置为 true 时,此示例才允许读取。
".read": "data.parent().child('isReadable').val() == true"
hasChild(子路径)
如果指定的子项存在,则返回 true。
参数: childPath
String
- 潜在子项位置的相对路径。
返回值: Boolean - 如果数据存在于指定的子路径中, true
;否则false
。
此示例仅允许写入包含子“名称”的数据。
".validate": "newData.hasChild('name')"
有孩子([孩子])
检查儿童是否存在。
参数: children
Array
可选- 必须全部存在的子键数组。
返回值: Boolean
值 - 如果(指定的)子项存在则为true
;否则false
。
如果未提供参数,则如果RuleDataSnapshot有任何子项,它将返回 true。如果提供了子名称数组,则仅当所有指定的子名称都存在于RuleDataSnapshot中时才会返回 true。
此示例仅允许写入包含一个或多个子项的数据。
".validate": "newData.hasChildren()"
此示例仅允许写入包含“name”和“age”子项的数据。
".validate": "newData.hasChildren(['name', 'age'])"
存在()
如果此RuleDataSnapshot包含任何数据,则返回 true。
返回值: Boolean
- 如果RuleDataSnapshot包含任何数据, true
;否则false
。
如果此RuleDataSnapshot包含任何数据,则exists 函数将返回true。它纯粹是一个便利函数,因为data.exists()
相当于data.val() != null
。
只要没有现有数据,此示例就允许在此位置进行写入。
".write": "!data.exists()"
获取优先级()
获取RuleDataSnapshot中数据的优先级。
返回值: ( String
、 Number
、 Null
) - 此RuleDataSnapshot中数据的优先级。
此示例确保正在写入的新数据具有优先级
".validate": "newData.getPriority() != null"
isNumber()
如果此RuleDataSnapshot包含数值,则返回 true。
返回值: Boolean
值 - 如果数据是数字,则为true
;否则false
。
此示例确保写入的新数据具有带有数值的子“age”。
".validate": "newData.child('age').isNumber()"
isString()
如果此RuleDataSnapshot包含字符串值,则返回 true。
返回值: Boolean
- 如果数据是String
true
;否则false
。
此示例确保写入的新数据具有带有字符串值的子“name”。
".validate": "newData.child('name').isString()
是布尔值()
如果此RuleDataSnapshot包含布尔值,则返回 true。
返回值: Boolean
- 如果数据是Boolean
, true
;否则false
。
此示例确保写入的新数据具有带有布尔值的子“active”。
".validate": "newData.child('active').isBoolean()"
字符串:属性
长度
返回字符串的长度。
返回值: Number
- 字符串中的字符数。
此示例要求字符串至少包含 10 个字符。
".validate": "newData.isString() && newData.val().length >= 10"
字符串:方法
包含(子字符串)
如果字符串包含指定的子字符串,则返回 true。
参数: substring
String
- 要查找的子字符串。
返回值: Boolean
- 如果字符串包含指定的子字符串, true
;否则false
。
此示例要求数据是包含“@”的字符串。
".validate": "newData.isString() && newData.val().contains('@')"
开始于(子字符串)
如果字符串以指定的子字符串开头,则返回 true。
参数: substring
String
- 在开头查找的子字符串。
返回值: Boolean
- 如果字符串包含指定的子字符串, true
;否则false
。
如果auth.token.identifier
以“internal-”开头,则此示例允许读取访问
".read": "auth.token.identifier.beginsWith('internal-')"
以(子字符串)结尾
如果字符串以指定的子字符串结尾,则返回 true。
参数: substring
String
- 在末尾查找的子字符串。
返回值: Boolean
- 如果字符串以指定子字符串结尾则为true
;否则false
。
如果auth.token.identifier
以“@company.com”结尾,则此示例允许读取访问
".read": "auth.token.identifier.endsWith('@company.com')"
替换(子字符串,替换)
返回字符串的副本,其中指定子字符串的所有实例都替换为指定的替换字符串。
参数: substring String
- 要查找的子字符串。 replacement String
- 用于替换子字符串的字符串。
返回值: String
- 用 replacement 替换 substring 后的新字符串。
replace()
方法与 JavaScript replace()
方法略有不同,因为它用指定的替换字符串替换指定子字符串的所有实例,而不仅仅是第一个实例。
由于键中不允许使用句点,因此我们需要在存储字符串之前使用句点对字符串进行转义。电子邮件地址就是一个例子。假设我们的/whitelist/
节点中有一个列入白名单的电子邮件地址列表:
{
"user": {
"$uid": {
"email": <email>
}
},
"whitelist": {
"fred@gmail%2Ecom": true,
"barney@aol%2Ecom": true
}
}
我们可以制定一条规则,仅允许添加用户的电子邮件地址位于/whitelist/
节点中:
{
"rules": {
"users": {
"$uid": {
".read": "true",
".write": "root.child('whitelist').child(newData.child('email').val().replace('.', '%2E')).exists()"
}
}
}
}
toLowerCase()
返回转换为小写的字符串的副本。
返回值: String
- 转换为小写的字符串。
如果/users
下存在全小写的auth.token.identifier
,则此示例允许读取访问。
".read": "root.child('users').child(auth.token.identifier.toLowerCase()).exists()"
toUpperCase()
返回转换为大写的字符串的副本。
返回值: String
- 转换为大写的字符串。
如果/users
下存在全部大写的auth.token.identifier
,则此示例允许读取访问。
".read": "root.child('users').child(auth.token.identifier.toUpperCase()).exists()"
匹配(正则表达式)
如果字符串与指定的正则表达式文字匹配,则返回 true。
返回值: Boolean
值 - 如果字符串与正则表达式文本 regex 匹配, true
;否则false
。
请参阅完整规则正则表达式文档。
运营商
+(添加)
用于添加变量或用于字符串连接。
以下示例确保新值将现有值恰好增加 1。这对于实现计数器很有用:
".write": "newData.val() === data.val() + 1"
".validate": "root.child('room_names/' + $room_id).exists()"
-(求负或减去)
用于对规则表达式中的某个值求反或减去两个值。
此验证规则检查新值是否是以下位置处的子值的倒数:
".validate": "newData.val() === -(data.child('quantity').val())"
以下示例使用减法来确保只能读取最近十分钟的消息:
".read": "newData.child('timestamp').val() > (now - 600000)"
*(乘法)
用于在规则表达式中乘以变量。
此验证规则检查新值是否等于价格和数量的乘积(两个现有值):
".validate": "newData.val() === data.child('price').val() * data.child('quantity').val()"
/(除)
用于划分规则表达式中的变量。
在以下示例中,验证规则确保存储的数据是其他地方存储的总数据的平均值:
".validate": "newData.val() === data.parent().child('sum').val() / data.parent().child('numItems').val()"
%(模数)
用于查找规则表达式中一个变量除以另一个变量的余数。
此规则验证只能写入偶数:
".validate": "newData.val() % 2 === 0"
===(等于)
用于检查规则表达式中的两个变量是否具有相同的类型和值。
以下规则使用 === 运算符仅向用户帐户的所有者授予写访问权限。用户的 uid 必须与键 ( $user_id
) 完全匹配,规则才能评估为 true。
"users": {
".write": "$user_id === auth.uid"
}
!==(不等于)
用于检查规则表达式中的两个变量是否不相等。
以下读取规则确保只有登录用户才能读取数据:
".read": "auth !== null"
&& (和)
如果两个操作数都为 true,则计算结果为 true。用于评估规则表达式中的多个条件。
以下验证规则检查新数据是否是少于 100 个字符的字符串:
".validate": "newData.isString() && newData.val().length < 100"
|| (或者)
如果规则表达式中的一个操作数为 true,则计算结果为 true。
在这个例子中,只要旧数据或新数据不存在,我们就可以写入。换句话说,如果我们要删除或创建数据,但不能更新数据,则可以写入。
".write": "!data.exists() || !newData.exists()"
! (不是)
如果其单个操作数为 false,则计算结果为 true。在规则表达式中,!运算符通常用于查看数据是否已写入某个位置。
以下规则仅在指定位置没有数据时允许写入访问:
".write": "!data.exists()"
>(大于)
用于检查规则表达式中的一个值是否大于另一个值。
此验证规则检查写入的字符串不是空字符串:
".validate": "newData.isString() && newData.val().length > 0"
<(小于)
用于检查规则表达式中的一个值是否小于另一个值。
此验证规则检查字符串是否少于 20 个字符:
".validate": "newData.isString() && newData.val().length < 20"
>=(大于或等于)
用于检查规则表达式中的一个值是否大于或等于另一个值。
此验证规则检查写入的字符串不是空字符串:
".validate": "newData.isString() && newData.val().length >= 1"
<=(小于或等于)
用于检查规则表达式中的一个值是否小于或等于另一个值。
此验证规则可确保将来无法添加新数据:
".validate": "newData.val() <= now"
? (三元运算符)
用于评估条件规则表达式。
三元运算符采用三个操作数。 ? 之前的操作数是条件。如果条件计算结果为 true,则计算第二个操作数。如果条件为假,则计算第三个操作数。
对于以下验证规则,新值可以是数字或布尔值。如果是数字,则必须大于 0。
".validate": "newData.isNumber() ? newData.val() > 0 : newData.isBoolean()"