1. 设置
获取源代码
在此 Codelab 中,您将从一个几乎完整的 Friendly Chat 示例应用版本开始,因此您首先需要做的是克隆源代码:
$ git clone https://github.com/firebase/codelab-friendlychat-web --branch security
然后,进入 security-start
目录,在此 Codelab 的剩余部分中,您将在此目录中工作:
$ cd codelab-friendlychat-web/security-start
现在,安装依赖项,以便运行代码。如果您的互联网连接速度较慢,则可能需要一两分钟的时间:
$ npm install && (cd functions && npm install)
了解此代码库
security-solution/
目录包含示例应用的完整代码。您将在 security-start
目录中完成此 Codelab,其中缺少身份验证实现的几个重要部分。security-start/
和 security-solution/
中的关键文件和功能如下:
functions/index.js
包含 Cloud Functions 函数代码,您将在此处编写身份验证屏蔽函数。public/
- 包含聊天应用的静态文件public/scripts/main.js
- 聊天应用 JS 代码 (src/index.js
) 的编译目标位置src/firebase-config.js
- 包含用于初始化聊天应用的 Firebase 配置对象src/index.js
- 您的 Chat 应用 JS 代码
获取 Firebase CLI
模拟器套件是 Firebase CLI(命令行界面)的一部分,您可以使用以下命令将其安装到您的机器上:
$ npm install -g firebase-tools@latest
使用 webpack 构建 JavaScript,这将在 public/scripts/ 目录中创建 main.js。
webpack build
接下来,确认您使用的是最新版本的 CLI。此 Codelab 适用于 11.14 或更高版本。
$ firebase --version 11.14.2
关联到您的 Firebase 项目
如果您还没有 Firebase 项目,请在 Firebase 控制台中创建一个新的 Firebase 项目。记下您选择的项目 ID,因为您稍后需要用到它。
现在,您需要将此代码连接到您的 Firebase 项目。首先,运行以下命令以登录 Firebase CLI:
$ firebase login
接下来,运行以下命令以创建项目别名。将 $YOUR_PROJECT_ID
替换为您的 Firebase 项目的 ID。
$ firebase use $YOUR_PROJECT_ID
现在,您可以运行应用了!
2. 运行模拟器
在本部分中,您将在本地运行应用。这意味着,现在可以启动 Emulator Suite 了。
启动模拟器
在 Codelab 源代码目录内,运行以下命令以启动模拟器:
$ firebase emulators:start
这将通过 http://127.0.0.1:5170 提供您的应用,并随着您做出更改不断重新构建源代码。您只需在浏览器中执行本地强制刷新 (ctrl-shift-r) 即可看到所做的更改。
您应该会看到类似于以下内容的输出:
i emulators: Starting emulators: auth, functions, firestore, hosting, storage ✔ functions: Using node@16 from host. i firestore: Firestore Emulator logging to firestore-debug.log ✔ firestore: Firestore Emulator UI websocket is running on 9150. i hosting[demo-example]: Serving hosting files from: ./public ✔ hosting[demo-example]: Local server: http://127.0.0.1:5170 i ui: Emulator UI logging to ui-debug.log i functions: Watching "[...]" for Cloud Functions... ✔ functions: Loaded functions definitions from source: beforecreated. ✔ functions[us-central1-beforecreated]: providers/cloud.auth/eventTypes/user.beforeCreate function initialized (http://127.0.0.1:5011/[...]/us-central1/beforecreated). i Running script: npm start > security@1.0.0 start > webpack --watch --progress [...] webpack 5.50.0 compiled with 1 warning in 990 ms
看到 All emulators ready 消息后,应用便可以开始使用了。
3. 实现多重身份验证 (MFA)
此代码库中已部分实现 MFA。您将添加代码,以便先为用户注册 MFA,然后提示已注册 MFA 的用户提供第二重身份验证。
在您的编辑器中,打开 src/index.js
文件并找到 startEnrollMultiFactor()
方法。添加以下代码以设置 reCAPTCHA 验证程序,以防止电话滥用行为(reCAPTCHA 验证程序设置为不可见,不会向用户显示):
async function startEnrollMultiFactor(phoneNumber) {
const recaptchaVerifier = new RecaptchaVerifier(
"recaptcha",
{ size: "invisible" },
getAuth()
);
然后,找到 finishEnrollMultiFactor()
方法并添加以下代码以注册第二个因素:
// Completes MFA enrollment once a verification code is obtained.
async function finishEnrollMultiFactor(verificationCode) {
// Ask user for the verification code. Then:
const cred = PhoneAuthProvider.credential(verificationId, verificationCode);
const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(cred);
// Complete enrollment.
await multiFactor(getAuth().currentUser)
.enroll(multiFactorAssertion)
.catch(function (error) {
alert(`Error finishing second factor enrollment. ${error}`);
throw error;
});
verificationId = null;
}
接下来,找到 signIn
函数,然后添加以下控制流,以提示已注册多重身份验证的用户输入其第二重身份验证因素:
async function signIn() {
// Sign in Firebase using popup auth and Google as the identity provider.
var provider = new GoogleAuthProvider();
await signInWithPopup(getAuth(), provider)
.then(function (userCredential) {
// User successfully signed in and is not enrolled with a second factor.
})
.catch(function (error) {
if (error.code == "auth/multi-factor-auth-required") {
multiFactorResolver = getMultiFactorResolver(getAuth(), error);
displaySecondFactor(multiFactorResolver.hints);
} else {
alert(`Error signing in user. ${error}`);
}
});
}
实现的其余部分(包括此处调用的函数)已完成。如需了解它们的运作方式,请浏览文件的其余部分。
4. 在模拟器中尝试使用多重身份验证登录
现在试用 MFA 实现!确保模拟器仍在运行,然后访问 localhost:5170
中托管的本地应用。请尝试登录,当系统提示您提供 MFA 代码时,您会在终端窗口中看到该 MFA 代码。
由于模拟器完全支持多重身份验证,您的开发环境可以完全独立。
如需详细了解如何实现多重身份验证,请参阅我们的参考文档。
5. 创建屏蔽函数
有些应用仅供特定用户群组使用。对于这些情况,您需要能够为用户创建自定义注册或登录要求。
这就是屏蔽函数的作用:创建自定义身份验证要求的方法。它们是 Cloud Functions 函数,但与大多数函数不同,它们会在用户尝试注册或登录时同步运行。
如需创建阻塞函数,请在编辑器中打开 functions/index.js
,然后找到注释掉的 beforecreated
函数。
将其替换为以下代码,仅允许域名为 example.com 的用户创建账号:
exports.beforecreated = beforeUserCreated((event) => {
const user = event.data;
// Only users of a specific domain can sign up.
if (!user.email || !user.email.endsWith("@example.com")) {
throw new HttpsError("invalid-argument", "Unauthorized email");
}
});
6. 在模拟器中试用屏蔽函数
如需试用屏蔽功能,请确保模拟器正在运行,然后在 Web 应用的 localhost:5170
中退出账号。
然后,尝试使用不以 example.com
结尾的电子邮件地址创建账号。屏蔽函数会阻止操作成功。
现在,请使用以 example.com
结尾的电子邮件地址重试。账号将成功创建。
借助屏蔽函数,您可以创建与身份验证相关的任何限制。如需了解详情,请参阅参考文档。
回顾
太棒了!您向 Web 应用添加了多重身份验证以帮助用户保障账号安全,然后还使用屏蔽功能为用户创建了注册要求的自定义要求。您绝对可以赢取一张 GIF 图片!