Firebase数据库访问被拒绝并设置了权限 [英] Firebase database access denied with permission set

本文介绍了Firebase数据库访问被拒绝并设置了权限的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我仔细查看了类似问题的其他答案,据我所知,一切均已正确设置,但仍然无法访问.

I have carefully looked at other answers to similar questions and as far as I can tell everything is set correctly but still access is denied.

最小工作示例:

路径"user/{uid}"的我的Firebase实时数据库安全规则如下

My Firebase Live Database Security Rule for the path 'user/{uid}' is as follows

"rules": {
          "user": {
                    "$uid": {
                              ".read":     "auth.uid === $uid",
                              ".write":    "auth.uid === $uid && !data.exists() "
                            }
                  }
       }

在打字稿中,我尝试读取某些用户的'user/{uid}'.

in the typescript I attempt to read 'user/{uid}' for some user.

//Firebase and firebase-fcuntions import
const firebase       = require("firebase");
const functions      = require('firebase-functions');

//Reference to root of database
const rootdb = firebase.database();

//Read data
function foo(data, context){
    return rootdb.ref('user').child(context.auth.uid).once('value')
    .then(snap => //do stuff)
    .catch( err => { console.log("Unsuccessful.")})
 }

//Make call available from application using authentication
exports.enable_foo = functions.https.onCall( (data, context)  => foo(data, context)  );

firebase上的日志显示:

The logs on firebase display:

错误:/user/XCRR0JK3xxZMoyoKzTIeQ2n1HcY2的权限被拒绝:客户端没有访问所需数据的权限.一个...

Error: permission_denied at /user/XCRR0JK3xxZMoyoKzTIeQ2n1HcY2: Client doesn't have permission to access the desired data. a...

并显示执行捕获路径的未成功"消息.

and the "Unsuccesful" message for the catch path of execution prints.

我想念什么?

编辑1

我应该提到,与上面的最小工作示例相反,实际方法确实会检查正在登录的用户并打印用户auth.uid,以便我可以确认用户已登录.

I should mention that the actual method, as opposed to the minimum working example above, does check for the user being logged in and prints the user auth.uid so I can confirm the user is logged in.

//Firebase and firebase-fcuntions import
const firebase       = require("firebase");
const functions      = require('firebase-functions');

//Reference to root of database
const rootdb = firebase.database();

//Read data
function foo(data, context){


    // Checking that the user is authenticated.
    if (!context.auth) {
        console.log("No authentication.")
        throw new functions.https.HttpsError('Authentication', "You are not authorized to execute this function." );
    }

    console.log(  context.auth.uid )
    return rootdb.ref('user').child(context.auth.uid).once('value')
    .then(snap => //do stuff)
    .catch( err => { console.log("Unsuccessful.")})
 }

//Make call available from application using authentication
exports.enable_foo = functions.https.onCall( (data, context)  => foo(data, context)  );

执行此功能时,在打印时,用户的{uid}会显示在日志中.

When I execute this function the {uid} of the user shows up in the logs when I print it.

编辑2

用"firebase-admin"代替"firebase"要求似乎可以解决"该问题,也就是说,它允许读取.

Replacing the 'firebase' requirement by "firebase-admin" appears to "fix" the issue, that is to say it allows the read.

我对此有一个安全问题,即,如果我使用"firebase"要求,则经过身份验证和DO有权访问资源的用户将被拒绝说该资源.需要完全访问权限"firebase-admin"以允许用户访问(读取或写入)资源似乎已被杀死,这是意料之外的.

I have a security concern with this, namely that users who are authenticated and DO have access to a resource are denied said resource if I use the "firebase" requirement. Needing the full access "firebase-admin" to allow a user to access(read or write) a resource seems over kill and unintended.

所以,我想现在的问题是:这是预期的行为吗?

So, I suppose the question now is: is this intended behaviour?

推荐答案

当您的客户端应用调用可调用函数时,已认证用户的身份将传递给该函数,但这并不意味着该函数会以某种方式自动使用用户的凭据初始化任何其他模块.因此,如果您导入Firebase客户端SDK,则它可以在未经身份验证的模式下有效运行(如果它可以正常工作-只能在浏览器环境中运行,而不是在nodejs上运行).

When your client app invokes a callable function, the identity of the authenticated user is passed along to the function, but that doesn't mean the function is somehow automatically initializing any other modules with the user's credentials. So, if you import the Firebase client SDK, it is effectively running in unauthenticated mode (if it works at all - it was meant to run in browser environments, not nodejs).

由于后端代码在用户无法修改的特权环境中运行,因此通常可以安全地运行任何代码,因为您已编写了代码,并且确切知道了它的作用.因此,建议用户firebase-admin进行访问,这主要是为了后端而不是客户端应用程序.

Since backend code runs in a privileged environment that the user can't modify, it's typically said to be safe to run any code, since you wrote it, and you know exactly what it does. That's why it's recommended to user firebase-admin for access, which is meant primarily for backends and not client apps.

现在,如果您担心用户可能会触发该函数并尝试使其代表他们执行某些不应执行的操作,则您将必须为此编写一些代码.通常的选择是验证是否允许UID执行该功能将要执行的操作.这意味着复制通常用于保护数据库的任何安全规则的检查.

Now, if your concern is that the user might trigger the function and try to make it do something on their behalf that they shouldn't be able to do, you will have to write some code for that. The typical choice is to validate that the UID is allowed to do what the function is going to do. This means duplicating the checks of any security rules that would normally be used to protect the database.

您的其他选择(会影响性能)是使用 databaseAuthVariableOverride 告诉管理员SDK应该使用其他UID来访问实时数据库.然后它将遵守所有安全规则.这里的问题是,您必须针对每个请求初始化 -admin实例 ,然后删除它们,以免泄漏内存.我在另一个示例中显示了此示例使用HTTP函数的答案来接收auth ID令牌,验证其UID,然后使用UID初始化SDK.由于您正在使用可调用类型函数,因此验证已经为您完成,因此您所要做的就是以相同的方式使用该函数中给定的UID.

Your other choice, which is going to suffer in performance, is to use the databaseAuthVariableOverride to tell the Admin SDK that it should use a different UID to access Realtime Database. Then it will respect all security rules. The problem here is that you have to init and then delete the firebase-admin instance for each request so that you don't leak memory. I show an example of this in another answer that uses an HTTP function to receive an auth ID token, validate its UID, and use the UID to init the SDK. Since you are using a callable type function, the validation has already been done for you, so all you have to do is use the given UID from the function in the same way.

这篇关于Firebase数据库访问被拒绝并设置了权限的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆