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 up、sign out、reset password、delete 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 不运行任何后端代码(至少现在是这样)。对于更复杂的应用程序,您可能需要一些服务器端代码,主要用于运行由于某种原因您不希望或无法在前端运行的东西,例如:
请记住,即使您需要一个后端,它也将拥有他们曾经拥有的 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 个月之后,你应得的。快乐的火基础。