在 Firebase 实时数据库规则中验证匿名用户的显示名称
Posted
技术标签:
【中文标题】在 Firebase 实时数据库规则中验证匿名用户的显示名称【英文标题】:Verifying an anonymous user's display name in Firebase realtime database rules 【发布时间】:2018-07-12 07:39:19 【问题描述】:我正在为匿名用户设置一个显示名称,并希望确保新值与此设置的显示名称相匹配。以下规则失败:
"name": ".validate": "newData.val() == auth.token.name"
这是为什么? docs 表示显示名称存储在auth.token.name
中。
以下是我的 Firebase 规则的完整副本:
"rules":
".read": false,
".write": false,
"messages":
".read": true,
"$message":
".write": "auth != null",
".validate": "newData.hasChildren(['createdAt', 'text', 'user'])",
"createdAt": ".validate": "newData.val() == now" ,
"text": ".validate": "newData.isString() && newData.val().length > 0" ,
"user":
".validate": "newData.hasChildren(['_id', 'name'])",
"_id": ".validate": "newData.val() == auth.uid" ,
"name": ".validate": "newData.val() == auth.token.name" ,
"$other": ".validate": false
,
"$other": ".validate": false
【问题讨论】:
请发布您的完整安全规则 JSON @RosárioPereiraFernandes 刚刚发布了它们。当我将 user.name 规则切换为仅验证 newData.isString() 时,我确认写入工作 您确定可以按照当前规则进行读写吗?因为根据the documentation:“较浅的安全规则覆盖较深路径的规则。子规则只能授予父节点已经声明的额外权限。它们不能撤销读取或写入权限。”。而且我看到您拒绝在根节点中进行读写。所以任何读或写都应该返回一个权限被拒绝的错误。º 它工作,因为模拟器读/写通过,我可以从我的应用程序中获取数据。我相信这意味着子规则不能撤销访问权限,但他们可以授予访问权限。我在模拟器中使用这个测试payload: "createdAt": ".sv": "timestamp" , "text": "Test 1", "user": "_id": "48c83bf9-7354-4720-838f-8b68e0addd51", "name": "Mike",
【参考方案1】:
正如我在 cmets 中提到的(取自 the documentation):
较浅的安全规则会覆盖较深路径的规则。子规则 只能授予父节点已经拥有的额外权限 宣布。他们不能撤销读取或写入权限。
这意味着您将无法写入数据库,因为您已在数据库的根节点处声明了.write:false
。您可能希望删除该行以具有如下结构:
"rules":
".read": false,
"messages":
".read": true,
"$message":
".write": "auth != null",
".validate": "newData.hasChildren(['createdAt', 'text', 'user'])",
"createdAt": ".validate": "newData.val() == now" ,
"text": ".validate": "newData.isString() && newData.val().length > 0" ,
"user":
".validate": "newData.hasChildren(['_id', 'name'])",
"_id": ".validate": "newData.val() == auth.uid" ,
"name": ".validate": "newData.val() == auth.token.name" ,
"$other": ".validate": false
,
"$other": ".validate": false
显示名称确实存储在auth.token.name
变量下。但是,当您在规则模拟器上使用默认的“匿名身份验证”时,这会发送一个带有此默认身份验证负载的请求:
"provider": "anonymous",
"uid": "N4EbtSX5HbM9JLjsW6hWT3NWzAx1"
请注意,在此负载下没有指定 name
,因此,auth.token.name
变量为 null,安全规则拒绝写入。
您可以在模拟器上使用您的自定义负载,只需将身份验证提供程序从“匿名”更改为“自定义”,它允许您编辑负载,因此您可以改用这个:
"provider": "anonymous",
"uid": "N4EbtSX5HbM9JLjsW6hWT3NWzAx1",
"token":
"name": "Mike"
使用此身份验证负载,您在 cmets 中提供的数据负载应该可以工作:
"createdAt":
".sv": "timestamp"
,
"text": "Test 1",
"user":
"_id": "48c83bf9-7354-4720-838f-8b68e0addd51",
"name": "Mike"
【讨论】:
我以前的规则是有效的,但我会看看这些变化。但是太糟糕了,匿名帐户不包含设置的显示名称。 所有提供者都不包括模拟器上设置的显示名称。那是因为模拟器只接受你提供给它的有效载荷。它不会访问您的实际数据库/身份验证来检查该 uid 是否具有相应的显示名称。 这个我明白,但我认为实际的 auth.token 将包含显示名称 当您在真实应用程序中进行测试时,它确实包含它。只是在模拟器上默认不包含它。 @RosárioPereiraFernandes 这是一个超级答案。我认为您还应该在展示如何在模拟器中为自定义有效负载编写 JSON 的部分中提到......如果有人需要测试他们的 CustomClaims,例如。 "moderator":true 或 "admin": true,即添加这些 KeyValue 对的地方(在 token 内)。因为在 firebase 文档中没有提到这个设置。将为开发人员节省大量时间。再次感谢。以上是关于在 Firebase 实时数据库规则中验证匿名用户的显示名称的主要内容,如果未能解决你的问题,请参考以下文章
用于 Firebase 实时数据库/Firebase 身份验证的 Android 唯一密钥