【问题标题】:Filter Firebase Realtime Database data based on authentication根据身份验证过滤 Firebase 实时数据库数据
【发布时间】:2018-09-17 13:01:09
【问题描述】:

我正在使用 Firebase 实时数据库作为 Android 应用的数据存储,现在我正在尝试根据用户权限实现一些基本过滤。

这是我的数据库:

{
    "admins" : { 
        `user1hash` : true
    },
    "clients" : {
        "client1hash" : {
            "owner": "user1hash",
            "name" : "Client 1"
        },
        "client2hash" : {
            "owner": "user1hash",
            "name" : "Client 2"
        },
        "client3hash" : {
            "owner": "user2hash",
            "name" : "Client 3"
        }
    }
}

我按照https://firebase.google.com/docs/database/security/securing-data基于查询的规则部分中的示例进行了如下定义:

{
  "rules": {
    "clients": {
      ".indexOn": "owner",
        ".read": "auth.uid != null && (root.child('admins/' + auth.uid).val() == true || query.orderByChild == 'owner' && query.equalTo == auth.uid)",
        ".write": "auth.uid != null",
        ".validate": "newData.hasChildren(['owner']) && newData.child('owner').val() == auth.uid"
    }
  }
}

这是我的客户端代码(Android):

        FirebaseDatabase database = FirebaseDatabase.getInstance();
        String authUser = FirebaseAuth.getInstance().getCurrentUser().getUid();
        DatabaseReference clientsDatabase = database.getReference("clients").orderByChild("owner").equalTo(authUser).getRef();
        clientsDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                // handle success
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                // handle error
            }
        });

所以基本上我只是希望能够获取所有客户端,但根据当前用户的访问规则过滤结果。访问规则非常简单,用户只能看到他是owner 的客户端,除了可以看到所有客户端的管理员用户。例如,如果这是由管理员 user1 运行的,他应该看到所有三个客户端,但如果这是由普通用户 user2 运行的,他应该只能看到客户端 3。

此实现适用于管理员,但我收到普通用户的权限错误。

我在 Firebase 控制台中尝试了规则模拟器,但它没有提供任何有关如何使用查询的文档。无论如何,我尝试将查询添加为像/clients?orderByChild=owner&equalTo=user2hash 这样的常规 URL 查询字符串,但这会在模拟器上返回一个空错误,并且没有说明原因。我在 Android 端遇到的错误也没有任何描述,只是一个通用权限错误。

【问题讨论】:

  • .orderByChild(".owner") 看起来像是一个错字,应该是.orderByChild("owner")(没有.)。
  • @FrankvanPuffelen 感谢您的回复,您是正确的,这是一个错字,我会更新我的问题。修复此问题后仍然出现相同的错误。另请注意,我在 firebase 控制台的规则模拟器中也遇到了一般权限错误。我无法在 firebase 控制台上找到任何日志或任何其他有关潜在错误的提示。
  • 我不认为控制台中的模拟器可以做任何类似查询的事情。它主要用于测试直接的读取或写入。但是,如果您尝试模拟基本的读取或写入,请将 JSON + 路径 + 数据 + 身份验证状态的屏幕截图添加到问题中,以便我们知道您在做什么。不过,总的来说,最好只关注一个问题中的一个问题。变量太多让人难以理解。
  • @FrankvanPuffelen 感谢您的回复。你是对的,看起来模拟器无法进行查询,无论如何这与我的问题无关,我也在应用程序上进行了测试,结果相同。

标签: android firebase firebase-realtime-database firebase-authentication firebase-security


【解决方案1】:

问题出在这句话中:

DatabaseReference clientsDatabase = 
    database.getReference("clients")
            .orderByChild("owner")
            .equalTo(authUser)
            .getRef();

特别是最后一行getRef(),它丢弃了您为构建查询所做的一切。上面的语句让clientsDatabase 完全一样:

DatabaseReference clientsDatabase = database.getReference("clients");

这很好地解释了语句失败的原因。

您需要保留返回的Query 并在其上附加您的听众:

DatabaseReference clientsDatabase = database.getReference("clients");
Query query = clientsDatabase.orderByChild("owner").equalTo(authUser);
query.addListenerForSingleValueEvent(new ValueEventListener() { ...

【讨论】:

  • 哦,这很有道理! Query-based Rules 的文档只有 JavaScript 示例,而且我之前没有使用过查询,所以我没有注意到这一点。我将对其进行测试,并让您知道它是如何工作的。提前致谢!
  • 你是对的,就是这样!非常感谢,非常感谢您的帮助!
猜你喜欢
  • 2017-12-26
  • 1970-01-01
  • 2018-01-28
  • 2021-01-22
  • 1970-01-01
  • 1970-01-01
  • 2017-01-08
  • 2019-04-19
  • 1970-01-01
相关资源
最近更新 更多