【问题标题】:Firebase as a back-end for AngularJSFirebase 作为 AngularJS 的后端
【发布时间】:2016-06-28 23:19:37
【问题描述】:

我很困惑。我开始使用 Ionic(仍在学习)和 AngularJS 进行开发。

现在,我尝试使用 Firebase 作为应用程序后端。我做了一个 facebook 身份验证过程,在用户通过身份验证后,一个对象被添加到数据库中(具有这些属性:名称、用户 ID 和个人资料图片)。

到目前为止一切顺利。我仍然不明白 Firebase 是为仅客户端应用程序设计的(作为任何后端服务的替代品),还是也为 NodeJS 之类的东西而设计?

我提出这个问题的原因,将作为示例提出:

现在是黄金问题,假设我需要向用户添加一个单独的“auth_level”(例如)属性。这发生在 .js 服务(客户端)中。客户可以访问它,因此他可以更改自己的用户名等内容。

return { 'name': userData.name, 'profilePic': 'http://graph.facebook.com/' + userData.id + '/picture', 'userId': userData.id };

是的,我知道我可以创建规则来阻止用户创建新对象,但是对于上面的示例 - 他已经拥有写入权限以便推送到数据库。 在我看来,这似乎是安全使用 Fireabse 的唯一方法,中间有某种桥(例如 NodeJS),但是 Firebase 失去了“实时”功能,对吧?还是我错了?

所以首先 - 我错过了什么重要的东西吗?

其次,如果这确实不安全,您是否推荐任何其他实时后端方法?就像使用 MongoDB 这样的数据库,并让 Node 服务器执行所有过滤并通过 Web 套接字与客户端通信。

我对混合移动开发尤其是 AngularJS 的整个世界非常陌生,我曾经做过很多 PHP(主要是 Laravel),但这对我来说似乎有点黑暗。我不习惯将此类敏感数据暴露给客户端。

再次抱歉,如果我在这里看起来有点愚蠢,但我将不胜感激。

【问题讨论】:

  • Firebase 可以通过其安全规则得到保护,这些规则在此处记录:firebase.com/docs/security/guide。您可能已经阅读过这些内容,但除非您表明您已经尝试保护您的数据并解释您认为哪个部分仍然不安全,否则这个问题太宽泛了。
  • 我也重新标记了您的问题。如果您阅读了每个标签中的帖子,您会很好地了解人们如何使用 Firebase 身份验证和安全性来保护他们的数据,以及他们经常遇到的问题。
  • @FrankvanPuffelen 感谢您的回复。我知道我可以应用一些安全规则,但是当为用户创建 Firebase 条目时(在 facebook 身份验证之后),我可以强制从 facebook 推送原始数据,而不能以不同的名称推送,例如,使用 ONLY AngularJS 和 Firebase?
  • 你可以控制谁写。您可以验证他们所写的是正确的结构。但是您无法验证用户写入的值是否来自 Facebook。如果您想确定这些值,请构建一个由可信代码(即您控制的流程)运行的验证步骤。
  • @FrankvanPuffelen 喜欢对某些 PHP 服务的 HTTP 请求以处理数据?还是 NodeJS 服务器?是这个意思吗?

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


【解决方案1】:

TL;DR - 如果您不需要 firebase 中用户处理的基本概念,请跳至下面的“答案”


基本概念

我有非常相似的问题,我也来自常规后端(但在 node.js 中)。让我先从一个例子开始(例如使用 js/mongoose,但请耐心等待):

这是用户模型在常规后端应用程序中的样子:

var userSchema = new mongoose.Schema({
  // 2) Auth Data
  userId: ObjectId,
  email: String,
  password: String,
  facebookProfile: Mixed,

  // 3) User Info
  displayName: String,
  favoriteColor: String,
  profileImageURL: String,

  // 4) Secret Stuff
  userRole: String
});

// 1) Account Methods
userSchema.static.createAccount = function (userData) { ... };
userSchema.methods.attemptLogin = function (password) { ... };
userSchema.methods.forgotPassword = function () { ... };
userSchema.methods.resetPassword = function (token, newPassword) { ... };

如果将上面的示例迁移到 firebase,它将被拆分成很多东西,最终出现在不同的地方:

1) 帐户方法

让我们从最简单的开始。 Firebase 只负责所有这些。只需查看文档以获取sign upsign outreset passworddelete account 以及您需要的任何其他方法。所有这些都直接从前端安全地完成。

2) 验证数据

登录后,如果您在前端执行Auth.getAuth(),您将get an authData object(或只是auth)基本上:

  • 用户 ID (authData.uid)
  • 使用的提供程序类似于“密码”或“Facebook”(authData.provider)。
  • “提供商配置文件”。该属性与提供者同名 (auth[auth.provider])。

providerProfile 是一个包含来自提供者的信息的对象。如果the provider is password,配置文件只有电子邮件、profileImageURL 和 isTemporaryPassword。如果the provider was facebook(或其他社交网络)你会从用户的 facebook 帐户中获得一堆东西。

所有这些都由 firebase 在内部处理,当用户登录时它是免费的,因此您不必存储任何这些。但请记住,您不能直接编辑其中的任何内容,因为它不在数据库中。在 Firebase 仪表板中,这将出现在您的数据库中,但您可以在“登录和身份验证”标签下看到您的用户。

3) 用户信息(不要将其称为“个人资料”以避免混淆)

假设您想要以下信息:

  • 不在 providerProfile 中,因为您将自己生成它(如 'favoriteColor')
  • 至少不在其中一个提供商中,但您希望每个人都拥有它(例如“displayName”,即not in the 'password' provider
  • 您希望能够更改它(保留自定义 imageProfileURL,不一定是 facebook 或 gravatar)

在这种情况下,您只需像存储数据库中的任何其他数据一样存储它。例如,您的数据库可能有一个 userInfo 对象,如下所示:

{
  userInfo: {
    "e0cb8039-deb0-4264-8fde-ca82ece76cb0": {
      displayName: "John Snow",
      favoriteColor: "black",
      profileImageURL: "..."
    },
    "b84692f-03a9-4f5c-914d-f78d508b4665": {
      displayName: "Sansa Stark",
      favoriteColor: "red",
      profileImageURL: "..."
    }
  }
}

为保证此对象的安全,您可以添加如下规则:

{
  "rules": {
    ...
    "userInfo": {
      "$uid": {
        // this 'auth' is exaclty the 'authData' in the example above
        ".write": "auth.uid === $uid", // only owner can write
        ".read": "auth !== null"       // any authenticated user can read
      },
    ...
    }
  }
} 

4) 秘密资料

这与上面的示例非常相似。只需在根级别添加另一个具有不同安全规则的对象。

{
  userRoles: {
    "e0cb8039-deb0-4264-8fde-ca82ece76cb0": "admin",
    "ab84692f-03a9-4f5c-914d-f78d508b4665": "client" // not even necessary..
}

对于规则

{
  "rules": {
    ...
    "userRoles": {
      "$uid": {
        // only admins can edit roles
        ".write": "root.child('userRoles').child(auth.uid).val() === 'admin'",
        // Users can read their own roles. Admins can read anyones
        ".read": "auth.uid === $uid || 
           root.child('userRoles').child(auth.uid).val() === 'admin'"
      },
    ...
    }
  }
} 

这里的秘诀是保持数据平坦。我通常考虑两件事来构建我的数据:如何保护它(不同的安全级别总是针对不同的对象)以及我需要如何在前端检索它。


答案

现在,基本概念已经不存在了,我将对您的问题发表评论:

我做了一个 facebook 身份验证过程,在用户通过身份验证后,一个对象被添加到数据库中(具有这些属性:名称、用户 ID 和个人资料图片)。

将它们添加到数据库是可选的,您可以在 auth 对象中免费获得。

我仍然不明白 Firebase 是为仅客户端应用程序设计的(作为任何后端服务的替代品),还是也为 NodeJS 之类的东西而设计?

对于简单的应用程序,您不需要其他任何东西。您甚至可以使用 firebase-hosting 为静态资产(您的整个前端)提供服务。但你是对的,firebase 不运行任何后端代码(至少现在是这样)。对于更复杂的应用程序,您可能需要一些服务器端代码,主要用于运行由于某种原因您不希望或无法在前端运行的东西,例如:

  • 需要安全 API 令牌的东西(如支付或第三方 API)
  • 不适合前端的密集型任务(压缩视频)。 Firebase Queue 非常适合。
  • 不能为handled by firebase alone 的复杂数据库查询。如果太复杂,您可能需要elasticSearch 之类的东西。

请记住,即使您需要一个后端,它也将拥有他们曾经拥有的 1/3 的代码。没有更多的模型、api 请求处理、帐户逻辑......更少的代码更少的错误。

假设我需要为用户添加一个单独的“auth_level”(例如)属性。这发生在 .js 服务(客户端)中。客户可以访问它,因此他可以更改自己的用户名等内容。

正如我们在上面看到的,如果您添加到具有不同安全规则的不同对象,则不会。他可能会读,但不会写。通过规则,您甚至可以选择用户应该能够为自己设置哪些角色,哪些不能。

其次,如果这确实不安全,您是否推荐任何其他实时后端方法?就像使用 MongoDB 这样的数据库,让 Node 服务器执行所有过滤并通过 Web 套接字与客户端通信。

我们刚刚看到它并非不安全。但是如果我不得不建议其他实时解决方案,我会告诉你试试 Meteor,它就像你描述的那样。由于我不必坚持使用 firebase,恕我直言,您比我所知道的任何其他东西(包括 Meteor)都要好。

我对混合移动开发尤其是 AngularJS 的整个世界非常陌生,我曾经做过很多 PHP(主要是 Laravel),但这对我来说似乎有点黑暗。我不习惯将此类敏感数据暴露给客户端。

嘿,不要难过,这不仅对你来说是新的,对整个世界来说都是新的。我一直在考虑为 firebase/node/angular 创建一个样板,这可能会有所帮助。如果我这样做,我会回来并发布一个链接。有一堆基于用户角色的角度路由,我花了一段时间才弄好。

感谢您的回复。我知道我可以应用一些安全规则,但是当为用户创建 Firebase 条目时(在 facebook 身份验证之后),我可以强制从 facebook 推送原始数据,而不能以不同的名称推送,例如,使用 ONLY AngularJS 和 Firebase?

当然可以,但是由于您可以直接从前端获取 authData,因此您可能不需要。如果您想在数据库中保留它的副本,可以说,因为您需要从用户未登录的地方读取,只需对规则使用如下内容:

// The old data has to be empty
// The new data has to be exactly like the user providerProfile
".validate": "!data.exists() && 
  newData.val() === auth[auth.provider]"

呸!这是一个(可能是不必要的)冗长的答案。但我希望在我刚开始的时候就能找到那种想法。文档很棒,但示例只是较小的部分,可能很难组合在一起。无论如何,在没有答案的 1 1/2 个月之后,你应得的。快乐的火基础。

【讨论】:

    猜你喜欢
    • 2013-07-10
    • 2016-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-24
    • 1970-01-01
    • 2018-10-06
    相关资源
    最近更新 更多