对管理员和普通用户使用相同的 Auth 方法时发生用户冲突 | Firebase 身份验证
User conflict when using same Auth method for Admin and Normal users | Firebase Auth
我正在开发 android 应用程序的管理模块。管理模块是一个基于 Angular 的网络应用程序。 Firebase auth(Email/password) 用于以管理员身份登录。我已经向 firebase 添加了一个手动凭据条目,管理员正在使用这些凭据登录(因为管理员没有注册功能)
另一方面 Android 开发人员也使用相同的 Auth 方法登录用户。因此 android 应用程序的用户能够使用他们的凭据登录管理模块。
如何防止 android 用户登录网络应用程序。是否有任何方法或规则可用于过滤传入的登录请求并仅在电子邮件属于管理员时才允许登录?
Firebase 不知道这里的 "Admin" 是什么。这是一个特定于您的应用程序的概念,因此您必须强制执行它。
无法让特定用户仅在特定平台上登录。这是因为 Firebase 明确区分了身份验证(用户证明他们是谁)和授权(用户有权访问资源)。您使用 Firebase 身份验证对用户进行身份验证,但是 "who can use what app" 是一个授权问题,因此它在其他地方处理。
如果您通过 Firebase 使用实时数据库、Cloud Firestore 或 Cloud Storage,您通常会在 Firebase server-side security rules 中强制执行我们的授权逻辑。由于这些是在服务器上自动强制执行的,因此用户无法绕过它们,并且无论用户在哪个平台上,它们都同样适用。
例如,我开始我的 Firestore 项目时使用的一个常见的第一条安全规则是:
service cloud.firestore {
match /databases/{database}/documents {
match /chat/{document} {
allow read;
allow write:
if isAdmin()
}
function isAdmin() {
return false;
}
}
}
这允许任何人读取数据,并且没有人可以写入数据,因为 isAdmin
总是 returns 错误。使用这些规则,我可以写入数据的唯一方法是使用 Admin SDK,因为使用此 SDK 的代码以提升的权限运行并绕过安全规则。一个完美的入门方式,并使用来自 Node.js 脚本的初始数据安全地填充我的数据库(在我最常见的情况下)。
然后在某些时候我会像你一样,添加一个应用程序管理员。那时我将他们的 UID 添加到安全规则中:
function isAdmin() {
return request.auth.uid == "KqEizsqUQ6XMkUgLUpNxFnzLm4F3"
|| request.auth.uid == "zYXmog8ySOVRrSGVt9FHFr4wJb92";
}
因此,我规则中的上述功能现在为两个特定的 Firebase 身份验证用户提供了对数据的写入权限。
这种方法适用于前几个用户,但在某些时候向规则添加 UID 会变得乏味且容易出错。那时我有两个主要选择:
- 将应用程序管理员的 UID 存储在数据库中。
- 以另一种方式识别应用程序管理员。
为了将 UID 存储在数据库中,您通常会手动将这些 UID 添加到数据库中,或者允许管理员识别其他管理员,并从应用程序中写入他们的 UID。无论哪种方式,安全规则都是这样的:
function isAdmin() {
return request.auth.uid == "KqEizsqUQ6XMkUgLUpNxFnzLm4F3"
|| request.auth.uid == "zYXmog8ySOVRrSGVt9FHFr4wJb92"
|| exists(/databases/$(database)/documents/admins/$(request.auth.uid))
;
}
所以最后一行现在也将 UID 存储在 admins
集合中的任何身份验证用户识别为应用程序管理员。
最后说一下,我想让我公司的每个人都成为应用程序管理员;我会这样做:
function isAdmin() {
return request.auth.uid == "KqEizsqUQ6XMkUgLUpNxFnzLm4F3"
|| request.auth.uid == "zYXmog8ySOVRrSGVt9FHFr4wJb92"
|| (request.auth.token.email_verified && request.auth.token.email.matches(".*@google.com"))
|| exists(/databases/$(database)/documents/admins/$(request.auth.uid))
;
}
所以这意味着任何拥有经过验证的@google.com 电子邮件地址的 Firebase 身份验证用户现在也是应用程序管理员。
如您所见,我分多个步骤构建这些规则,首先是简单地确定我将拥有具有特定权限的应用程序管理员,然后创建 isAdmin
函数。
我正在开发 android 应用程序的管理模块。管理模块是一个基于 Angular 的网络应用程序。 Firebase auth(Email/password) 用于以管理员身份登录。我已经向 firebase 添加了一个手动凭据条目,管理员正在使用这些凭据登录(因为管理员没有注册功能)
另一方面 Android 开发人员也使用相同的 Auth 方法登录用户。因此 android 应用程序的用户能够使用他们的凭据登录管理模块。
如何防止 android 用户登录网络应用程序。是否有任何方法或规则可用于过滤传入的登录请求并仅在电子邮件属于管理员时才允许登录?
Firebase 不知道这里的 "Admin" 是什么。这是一个特定于您的应用程序的概念,因此您必须强制执行它。
无法让特定用户仅在特定平台上登录。这是因为 Firebase 明确区分了身份验证(用户证明他们是谁)和授权(用户有权访问资源)。您使用 Firebase 身份验证对用户进行身份验证,但是 "who can use what app" 是一个授权问题,因此它在其他地方处理。
如果您通过 Firebase 使用实时数据库、Cloud Firestore 或 Cloud Storage,您通常会在 Firebase server-side security rules 中强制执行我们的授权逻辑。由于这些是在服务器上自动强制执行的,因此用户无法绕过它们,并且无论用户在哪个平台上,它们都同样适用。
例如,我开始我的 Firestore 项目时使用的一个常见的第一条安全规则是:
service cloud.firestore {
match /databases/{database}/documents {
match /chat/{document} {
allow read;
allow write:
if isAdmin()
}
function isAdmin() {
return false;
}
}
}
这允许任何人读取数据,并且没有人可以写入数据,因为 isAdmin
总是 returns 错误。使用这些规则,我可以写入数据的唯一方法是使用 Admin SDK,因为使用此 SDK 的代码以提升的权限运行并绕过安全规则。一个完美的入门方式,并使用来自 Node.js 脚本的初始数据安全地填充我的数据库(在我最常见的情况下)。
然后在某些时候我会像你一样,添加一个应用程序管理员。那时我将他们的 UID 添加到安全规则中:
function isAdmin() {
return request.auth.uid == "KqEizsqUQ6XMkUgLUpNxFnzLm4F3"
|| request.auth.uid == "zYXmog8ySOVRrSGVt9FHFr4wJb92";
}
因此,我规则中的上述功能现在为两个特定的 Firebase 身份验证用户提供了对数据的写入权限。
这种方法适用于前几个用户,但在某些时候向规则添加 UID 会变得乏味且容易出错。那时我有两个主要选择:
- 将应用程序管理员的 UID 存储在数据库中。
- 以另一种方式识别应用程序管理员。
为了将 UID 存储在数据库中,您通常会手动将这些 UID 添加到数据库中,或者允许管理员识别其他管理员,并从应用程序中写入他们的 UID。无论哪种方式,安全规则都是这样的:
function isAdmin() {
return request.auth.uid == "KqEizsqUQ6XMkUgLUpNxFnzLm4F3"
|| request.auth.uid == "zYXmog8ySOVRrSGVt9FHFr4wJb92"
|| exists(/databases/$(database)/documents/admins/$(request.auth.uid))
;
}
所以最后一行现在也将 UID 存储在 admins
集合中的任何身份验证用户识别为应用程序管理员。
最后说一下,我想让我公司的每个人都成为应用程序管理员;我会这样做:
function isAdmin() {
return request.auth.uid == "KqEizsqUQ6XMkUgLUpNxFnzLm4F3"
|| request.auth.uid == "zYXmog8ySOVRrSGVt9FHFr4wJb92"
|| (request.auth.token.email_verified && request.auth.token.email.matches(".*@google.com"))
|| exists(/databases/$(database)/documents/admins/$(request.auth.uid))
;
}
所以这意味着任何拥有经过验证的@google.com 电子邮件地址的 Firebase 身份验证用户现在也是应用程序管理员。
如您所见,我分多个步骤构建这些规则,首先是简单地确定我将拥有具有特定权限的应用程序管理员,然后创建 isAdmin
函数。