javascript - 让客户端创建用户但在通过身份验证之前不修改

标签 javascript backbone.js firebase firebase-security firebasesimplelogin

我正在使用 roder 中的 backbone.js 编写一个应用程序来学习。你可以在这里找到我实际得到的东西:https://the-todo-app.firebaseapp.com/

我的想法是允许人们使用 simpleLogin 和 facebook 在应用程序中注册以创建用户,然后他们将被重定向到他们的用户并被允许创建和修改他们的待办事项,但我遇到的问题是实际上每个用户都有在用户文件夹上写入的可能性,这意味着他们可以输入和删除或修改其他用户的数据。我想限制 firebase 的安全性,以允许他们根据他们的 id 创建他们的用户,但如果他们没有经过身份验证则不允许他们写。这是我实际拥有的:

{
  "rules": {
    ".read": true,
    ".write": true,
    ".validate": "data.hasChildren(['name', 'picture'])",
    "users": {
      "$user": {
        ".read": "$user == auth.id",
        ".write": "$user == auth.id"
      }          
    }
  }
}

Aso 尝试了这个:

{
  "rules": {
    ".read": true,
    "users": {
      "$user": {
        ".read": "$user == auth.id",
        ".write": "$user == auth.id"
      }          
    }
  }
}

但这种方法不允许客户端创建用户 ID。

这是我的数据实际的样子:

{
  "users" : {
    "10152111176005069" : {
      "name" : "Jhonnatan Gonzalez Rodriguez",
      "picture" : "url to pic"
    },
    "10154397958535078" : {
      "name" : "Diana Rincón P",
      "picture" : "url to pic"
    },
    "10152167159946759" : {
      "name" : "Sebastian Ayala",
      "picture" : "url to pic"
    }
  },
  "title" : "The todo app"
}

如果你们知道如何做到这一点,我将不胜感激。

根据 ArneHugo 的回答,我刚刚设置了这个规则并且似乎工作得很好,我需要做更多的测试才能确定。

{
  "rules": {
    "users": {
      ".write": "!data.child(auth.id).exists()",
      "$user": {
        ".read": "$user == auth.id",
        ".write": "$user == auth.id",
        ".validate": "newData.hasChildren(['name', 'picture'])"
      }          
    }
  }  
}

实际上,我必须将用户的 .read 规则添加为 true 以允许他们检查数据是否存在,这就是规则现在的样子。

{
  "rules": {
    "users": {
      ".read": "true",
      ".write": "!data.child(auth.id).exists()",
      "$user": {
        ".read": "$user == auth.id",
        ".write": "$user == auth.id",
        ".validate": "newData.hasChildren(['name', 'picture'])"
      }          
    }
  }  
}

这就是输出寻找匿名用户的方式

Attempt to write {"id":"6726363"} to /users/6726363 with auth=null
    /
    /users:.write: "!data.child(auth.id).exists()"
5:30: child() expects a string argument.
        => false
    /users/6726363:.write: "$user == auth.id"
        => false
    /users/6726363:.validate: "newData.hasChildren(['name', 'picture'])"
        => false

Validation failed.
Write was denied.

这就是寻找经过身份验证的用户的方式。

Attempt to write {"name":"6726363","picture":"fb picture"} to /users/6726363 with auth={"id":"6726363"}
    /
    /users:.write: "!data.child(auth.id).exists()"
        => true
    /users/6726363:.validate: "newData.hasChildren(['name', 'picture'])"
        => true
    /users/6726363:.validate: "newData.hasChildren(['name', 'picture'])"
        => true

Write was allowed.

这是匿名用户试图写入另一个用户数据的输出。

Attempt to write {"name":"6726363","picture":"fb picture"} to /users/10152111176005069 with auth=null
    /
    /users:.write: "!data.child(auth.id).exists()"
5:30: child() expects a string argument.
        => false
    /users/10152111176005069:.write: "$user == auth.id"
        => false
    /users/10152111176005069:.validate: "newData.hasChildren(['name', 'picture'])"
        => true

No .write rule allowed the operation.
Write was denied.

现在,做这个例子发现,一个在数据库中有一个已经存在的id的经过身份验证的用户可以像这样写另一个人的用户数据。

Attempt to write {"name":"6726363","picture":"fb picture"} to /users/10152111176005069 with auth={"id":"6726363"}
    /
    /users:.write: "!data.child(auth.id).exists()"
        => true
    /users/10152111176005069:.validate: "newData.hasChildren(['name', 'picture'])"
        => true
    /users/10152111176005069:.validate: "newData.hasChildren(['name', 'picture'])"
        => true

Write was allowed.

最佳答案

你想做的是完全可能的,我不同意 Kato 你应该使用不同类型的登录。

这就是你所需要的:

  "rules": {
    "users": {
      //".write": "!data.exists()", /* Edit: removed, as it always returned false */
      "$user": {
        ".read": "$user == auth.id",
        ".write": "$user == auth.id",
        ".validate": "newData.hasChildren(['name', 'picture'])"
      }          
    }
  }
  1. 新用户可以为自己添加一个 $user 条目。
  2. 除了他们自己的用户之外,任何用户都不能从 $user 读取信息。
  3. 除了他们自己的用户之外,任何用户都不能写入 $user(包括当他们首先创建它时,这确保了有效输入)。
  4. $user 条目必须有姓名和照片。 (请注意,我移动了您的验证规则。)

提示:使用 Firebase 中的模拟器来测试安全规则。这是一个很棒而简单的工具。

编辑

我做了一个测试,看看您是否真的需要一个读取规则来检查数据是否存在。 (答案:你不知道。)

具有以下安全规则

"test": {
    ".write": "!data.child(auth.id).exists()",
    "$user": {
        ".validate": "newData.hasChildren(['name', 'picture']) && $user == auth.id",
        ".read": "$user == auth.id",
        ".write": "$user == auth.id"
    }          
}

试图写一个新用户:

Attempt to write {"name":"Beardinator","picture":"i.imgur.com/axXz9sr.jpg"} to /test/1337 with auth={"id":"1337"}
    /:.write: "root.child('adminPanel').child('admins').child(auth.uid).val() != null"
20:67: child() expects a string argument.
        => false
    /test:.write: "!data.child(auth.id).exists()"
        => true
    /test/1337:.validate: "newData.hasChildren(['name', 'picture']) && $user == auth.id"
        => true
    /test/1337:.validate: "newData.hasChildren(['name', 'picture']) && $user == auth.id"
        => true

Write was allowed.

在我的测试中,我可以在没有关于“用户”的 .read 规则的情况下检查数据是否存在。

关于javascript - 让客户端创建用户但在通过身份验证之前不修改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24655892/

相关文章:

jquery - 我应该通过 RequireJS 加载所有内容(包括 jQuery)吗?

java - 如何列出所有根集合并获取所有产品?

javascript - 使用 xPath(javascript, jquery) 从 url 链接解析 html 页面

javascript - Underscore pluck 不适用于模型数组?

javascript - 文件观察器 'Babel' 可用于此文件。说明 : 'Transpiles ECMAScript 6 code to ECMAScript 5'

javascript - Backbone.js 中的一个 "listen to the router"(响应 View /模型中的路由器事件)如何?

ios - 从 firebase 获取用户消息

javascript - 如何使用云函数在 Firestore 中添加虚拟数据

javascript - Javascript 中的正则表达式匹配函数

javascript - 使用 Javascript 处理 JSON 响应