Firebase权限被拒绝

156

我对编程相对较新,遇到了些问题。

我有这段代码可以发送数据到Firebase。

app.userid = app.user.uid

var userRef = app.dataInfo.child(app.users);

var useridRef = userRef.child(app.userid);

useridRef.set({
  locations: "",
  theme: "",
  colorScheme: "",
  food: ""
});

然而,我一直收到以下错误:

FIREBASE警告:/users/(GoogleID)的设置失败:permission_denied 2016-05-23 22:52:42.707 firebase.js:227 Uncaught (in promise) Error: PERMISSION_DENIED: Permission denied(…)

当我试图查找此问题时,它谈论了Firebase的规则,这似乎是一种我还没学过的语言(或者只是超出我的能力范围)。有人可以解释一下是什么原因导致了这个问题吗?我认为原因是我要求其存储电子邮件和用户显示名称,但是您不能这样做,但是当我将其删除时,仍然存在相同的问题。是否有一种避免设置规则的方法,或者规则是我可以在一天内学会如何编写的东西,还是我完全不懂?

感谢任何帮助!

10个回答

314

默认情况下,在Firebase控制台中的项目数据库只能被管理员用户读/写(例如在Cloud Functions或使用Admin SDK的进程中)。除非您更改服务器端安全规则,否则常规客户端SDK的用户无法访问数据库。


您可以更改规则,使数据库仅对已验证的用户可读/写:

{
  "rules": {
    ".read": "auth != null",
    ".write": "auth != null"
  }
}

请参阅Firebase 数据库安全规则的快速入门

但由于您的代码没有签署用户,因此数据库会拒绝您访问数据。要解决这个问题,您需要允许未经身份验证的访问您的数据库或在访问数据库之前登录用户。

允许未经身份验证的访问您的数据库

目前最简单的解决方法(直到教程更新)是进入您项目中的控制台中的数据库面板,选择 Rules 选项卡并将其内容替换为以下规则:

{
  "rules": {
    ".read": true,
    ".write": true
  }
}

这将使得任何知道数据库URL的人都可以读写您的新数据库。 在进入生产之前,请确保再次保护您的数据库,否则有人可能会开始滥用它。

在访问数据库之前登录用户

为了实现更加安全的解决方案(稍微费时),请调用Firebase Authentication中的signIn...方法之一以确保用户在访问数据库之前已登录。最简单的方法是使用匿名认证

firebase.auth().signInAnonymously().catch(function(error) {
  // Handle Errors here.
  var errorCode = error.code;
  var errorMessage = error.message;
  // ...
});

当检测到登录时,请附加您的侦听器

firebase.auth().onAuthStateChanged(function(user) {
  if (user) {
    // User is signed in.
    var isAnonymous = user.isAnonymous;
    var uid = user.uid;
    var userRef = app.dataInfo.child(app.users);
    
    var useridRef = userRef.child(app.userid);
    
    useridRef.set({
      locations: "",
      theme: "",
      colorScheme: "",
      food: ""
    });

  } else {
    // User is signed out.
    // ...
  }
  // ...
});

1
谢谢 - 我们使用了不安全的修复方法,并且在回复类似问题时引用了您的答案,以解决 Firebase 权限问题,这是在 Ember 教程 中的进展。但是我们应该在哪里添加(安全的)匿名身份验证代码? - Dave Everitt
3
天啊,一个小时就这样过去了。我已经将这个值添加进去,但是数值是“假”的……我只是忽略了它。把它们改成“真”,然后一下子,应用程序就像你想象的那样工作了…… - Andy
哦我的天啊,我也是,一直搞不清为什么权限失败了,因为它们都已经设置为false了(直到我看到了你的评论)。唉,新手错误。当你要公开读取时,它们应该都是true的。感谢指出你自己的错误,你帮助我找到了答案。记录一下,我把规则改成了这样:".read": true,然后它就开始工作了。 - contractorwolf
@Andy 谢谢,跟我一样,看到你的评论解决了我的问题 ;) - Mahmudul Hasan Sohag
还遇到了“权限被拒绝”的用户访问错误,但似乎是因为 Firebase 数据库上的 Unix 时间戳和存储上的时间戳已经过期。但是添加身份验证规则到数据库后,读写操作又可以正常进行了。(请注意,这个错误不是时间访问被拒绝,或许 Firebase 可以研究一下)。感谢 FB、SO 和所有开发人员的辛勤工作! :) - verNsíon1

92

我面临类似的问题,发现这个错误是由于实时数据库读写操作的规则设置不正确造成的。默认情况下,谷歌 Firebase 现在加载的是云存储而非实时数据库。我们需要切换到实时数据库并应用正确的规则。

enter image description here

如我们所见,它说的是云 Firestore 而不是实时数据库。一旦切换到正确的数据库,请应用以下规则:

{
   "rules": {
       ".read": true,
       ".write": true
     }
 }

注意:

规则要小心。将读取和写入设置为true会使数据库容易被他人查看。

了解更多:

https://firebase.google.com/docs/database/security


4
该死的用户界面!我花了整整一天的时间,弄清楚为什么我的规则不同... 啊...原来是因为云端Firestore...谢谢! - Alexey Volodko

45

前往您提到的“数据库”选项。

  1. 在蓝色标题栏上,您会发现一个下拉菜单,上面写着 Cloud Firestore Beta
  2. 将其更改为“实时数据库”
  3. 进入规则并将.write .read两者都设置为true

摘自此处


2
我对此进行了负评,因为我认为这是不良建议。如果一位新手问如何让他们商店的前门打开,你不能仅仅建议他们把锁全部拆掉。禁用安全规则可能会导致灾难,并且如果用户数据泄露(很可能会发生),可能会面临非常昂贵的罚款。 - silviot
1
一个新手在这里卡了几天,会认为我的答案非常有帮助。我知道当我解决问题时有多开心,现在我正在帮助别人,而你们却在downvote @silviot,一个正在学习的新手,对生产没有任何影响。 - Ahmed Adewale
2
我理解你的观点,完全赞同你的精神。问题是,在你的回答中没有具体说明。如果你提出了警告,我会完全同意。但你只提到了去除安全检查所需的步骤,而没有警告可能产生的意外后果。 - silviot

10

前往数据库,标题旁边有两个选项:

云 Firestore,实时数据库

选择实时数据库并进入规则

将规则更改为 true。


3
我给这个帖子投了反对票,因为我认为这是错误的建议。如果新手询问如何让他们店铺的前门打开,你不能只建议他们完全移除锁。禁用安全规则可能会导致灾难,并且如果用户数据泄露(很可能会),还可能面临非常昂贵的罚款。此外,这是@ahmed-adewale答案的重复。 - silviot

4
  1. 打开 Firebase,在左侧选择数据库。
  2. 现在在右侧下拉菜单中选择 [实时数据库],并将规则更改为:
{
  "rules": {
    ".read": true,
    ".write": true
  }
}

10
已经在其他答案中提到过了。另外,当你建议这个时,请确保添加一个警告,因为这并不安全! - André Kool

4

好的,但你不想打开整个实时数据库! 你需要像这样的东西。

{
  /* Visit https://firebase.google.com/docs/database/security to learn more about security rules. */
  "rules": {
    ".read": "auth.uid !=null",
    ".write": "auth.uid !=null"
  }
}

或者
{
  "rules": {
    "users": {
      "$uid": {
        ".write": "$uid === auth.uid"
      }
    }
  }
}

2

如果提供的 Firebase 项目 ID 不正确,也会出现 PermissionDenied 错误。

请查看此指南以检查您的项目 ID:

Firebase 控制台:单击设置项目设置。 项目 ID 显示在顶部窗格中。


1

如果您正尝试在Firebase中重用旧项目,由于免费账户限制,那么您的数据库规则可能已经过时了。

就我而言,当我将读取和写入规则都设置为true时,错误401未经授权得到解决。

感谢这个伟大的社区!

来自巴西的最高敬意!


1

另一种解决方案是,如果您已经有凭据,可以自动创建或登录用户。以下是我使用普通JS的方法。

function loginToFirebase(callback)
{
    let email = 'xx@xx.com';
    let password = 'xxxxxxxxxxxxxx';
    let config =
    {
        apiKey: "xxx",
        authDomain: "xxxxx.firebaseapp.com",
        projectId: "xxx-xxx",
        databaseURL: "https://xxx-xxx.firebaseio.com",
        storageBucket: "gs://xx-xx.appspot.com",
    };

    if (!firebase.apps.length)
    {
        firebase.initializeApp(config);
    }

    let database = firebase.database();
    let storage = firebase.storage();

    loginFirebaseUser(email, password, callback);
}

function loginFirebaseUser(email, password, callback)
{
    console.log('Logging in Firebase User');

    firebase.auth().signInWithEmailAndPassword(email, password)
        .then(function ()
        {
            if (callback)
            {
                callback();
            }
        })
        .catch(function(login_error)
        {
            let loginErrorCode = login_error.code;
            let loginErrorMessage = login_error.message;

            console.log(loginErrorCode);
            console.log(loginErrorMessage);

            if (loginErrorCode === 'auth/user-not-found')
            {
                createFirebaseUser(email, password, callback)
            }
        });
}

function createFirebaseUser(email, password, callback)
{
    console.log('Creating Firebase User');

    firebase.auth().createUserWithEmailAndPassword(email, password)
        .then(function ()
        {
            if (callback)
            {
                callback();
            }
        })
        .catch(function(create_error)
        {
            let createErrorCode = create_error.code;
            let createErrorMessage = create_error.message;

            console.log(createErrorCode);
            console.log(createErrorMessage);
        });
}

2
从安全角度来看,这真的很糟糕。 - Friedrick
你能详细解释一下吗,@Friedrick?是在本地运行nodejs脚本时吗? - Vincent Gerris
@VincentGerris 用户的密码在离开设备之前应该先进行哈希处理。如果您的服务器上存储的是明文密码,那真的不太好。 - Friedrick
@Friedrick 我明白。但只要服务器是安全的,这通常就是会发生的事情,除非使用像Hashicorp的保险库这样的安全存储。如果是用于操作Firebase数据的客户端机器,那么情况就不那么糟糕了,这正是我正在尝试做的。因此,这取决于使用和暴露的程度。更糟糕的是,它可能出现在Angular/Ionic项目中,并最终出现在前端代码main.js中! - Vincent Gerris

-2

我也遇到了同样的问题。请确保你正在使用实时数据库而不是云数据库。然后按照以下方式更改规则以允许所有用户访问:

{
  "rules": {
    ".read": true,
    ".write": true
  }
}

默认情况下,Firestore 数据库只允许管理员从数据库中读取和写入数据,因此读/写规则将被设置为 false。


1
请不要这样做。拜托了。这是一个非常不安全的建议。 - Muhammad bin Yusrat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接