Firebase对象所有权与事件观察

我在iOS应用中使用了Firebase。 我希望每个对象都有一个creatorId属性,其值是通过身份validation的用户标识(具有Firebase身份validation对象的authData.uid )。 我正在使用自定义令牌生成器进行身份validation,但是问题也可以通过匿名login进行复制。

我希望用户只能阅读(和写,但让我们专注于阅读,因为这是我有我的问题)他们创build的对象。 换句话说,查询用户的authentication用户ID将匹配他们正在提取的对象的creatorId

当我制作查询和规则来实现这一点时,我遇到了权限问题。

这里是规则和安全的Firebase文档。

以下是我的Firebase仪表板对于Task对象的外观:

 + firebase-base + tasks + {task_id} + creatorId: + title: 

其中task_id是插入时由Firebase生成的唯一标识符。

我的规则看起来像这样(现在让我们忽略编写规则):

 { "rules": { "tasks": { "$task_id": { ".read": "auth.uid === data.child('creatorId').val()" } } } } 

读取一个特定的任务工作正常,但我希望能够使用observeEventType和相关函数进行查询,说:“获取所有我创build的任务”。 这对我不起作用。 我得到“权限被拒绝”的错误。

下面是我在Swift中的观察:

 let reference = Firebase(url: "https://{My-Firebase-Base-Reference}/tasks") reference.observeEventType(.ChildChanged, withBlock: { (snapshot: FDataSnapshot!) -> Void in // Success }) { (error: NSError!) in // Error: I get Permissions Denied here. } 

根据@ Ymmanuel的build议,我也试过在我的查询中更具体,就像这样:

 let reference = Firebase(url: "https://{My-Firebase-Base-Reference}/tasks") reference.queryOrderedByChild("creatorId").queryEqualTo({USER_UID}).observeEventType(.ChildChanged, withBlock: { (snapshot: FDataSnapshot!) -> Void in // Success }) { (error: NSError!) in // Error: I get Permissions Denied here. } 

这些块都没有工作,我总是得到“权限被拒绝”的错误。 我究竟做错了什么?

你所缺less的是,你假设安全规则是查询,这是不正确的。

检查链接中的“规则不过滤”部分。

安全规则只会validation您是否可以读取或写入Firebase数据库的特定path。

如果您只想接收特定用户的更改,则应使用Firebase查询。

例如,如果你想获得一个特定用户的所有任务,你应该这样做:

 let reference = Firebase(url: "https://{My-Firebase-Base-Reference}/tasks") reference.queryOrderedByChild("creatorId").queryEqualTo(YOUR_CURRENT_USER_UID).observeEventType(.ChildChanged, withBlock: { (snapshot: FDataSnapshot!) -> Void in // Success }) { (error: NSError!) in // Error: Get Permissions Denied Here. } 

通过这种方式,您可以获得与用户相关的所有事件,并通过应用安全规则来保护信息。

同样,如果你只想让创build者自己写任务,你也应该考虑创build任务的情况,写下如下的内容:

  "tasks": { //You need to include the $task_id otherwise the rule will seek the creatorId child inside task and not inside your auto-generated task "$task_id": { ".read": "auth.uid === data.child('creatorId').val()", //this is to validate that if you are creating a task it must have your own uid in the creatorId field and that you can only edit tasks that are yours... ".write":"(newData.child('creatorId').val() === auth.uid && !data.exists()) || (data.child('creatorId').val() === auth.uid && data.exists())", //you should add the index on to tell firebase this is a query index so your queries can be efficient even with larger amounts of children ".indexOn":"creatorId", } } 

(检查语法,但这是一般的想法)

几个意见:

如果本地持续打开,并且没有互联网连接,并且没有本地值,则不会调用任何块。

问题中的观察代码正在扰乱我,这是没有错的,但如果是这样的话可能会更清楚一点:

  reference.observeEventType(.ChildChanged, withBlock: { snapshot in print(snapshot.value) }, withCancelBlock: { error in print(error.description) }) 

编辑:

现在的问题更清楚了

我想让用户只能读取他们创build的对象。

我将通过以下演示:

Firebase结构:

 posts post_0 created_by: uid_0 msg: some message post_1 created_by: uid_1 msg: another message post_2 created_by: uid_2 msg: yippee 

以及允许用户只从他们创build的post节点读取的规则

 "rules": { ".read": false, ".write": false, "posts": { ".read": false, "$post_id": { ".read": "root.child('posts').child($post_id).child('created_by').val() == auth.uid", ".write": "auth != null" } } } 

然后代码来testing。 我们假设当前用户的uid是uid_0:

 let reference = self.myRootRef.childByAppendingPath("posts/post_0") reference.observeEventType(.ChildAdded, withBlock: { snapshot in print(snapshot.value) }, withCancelBlock: { error in print(error.description) }) 

上面的代码将允许从节点post_0读取,该节点是由created_by子项指示的后创build的uid_0。

例如,如果将path更改为posts / posts_1(或其他任何内容),则读取被拒绝。

这个答案我不是直接回答这个问题,就好像你期待的规则是'阻止'或'过滤'结果数据,这不是什么规则(每个其他答案)。

所以你可能想通过构build一个查询来拉出你想要工作的post的基础上像这样created_by = auth.uid不同的path

 let reference = self.myRootRef.childByAppendingPath("posts") reference.queryOrderedByChild("created_by").queryEqualToValue("uid_1") .observeEventType(.Value, withBlock: { snapshot in print(snapshot.value) }, withCancelBlock: { error in print(error.description) })