注册回调
同步 Firebase 用户到后端系统
概述
在现代应用中,用户管理是一个关键的功能。Firebase 提供了强大的身份验证服务,可以轻松地管理用户的创建和删除。然而,在某些场景下,我们需要将 Firebase 的用户数据与后端系统进行同步,以实现更复杂的业务逻辑或数据分析。本文将详细介绍如何通过 Firebase Cloud Functions 注册回调,将 Firebase 用户的创建和删除事件同步到后端 Java 服务。
本文将涵盖以下内容:
- 初始化 Firebase 项目
- 编写 Cloud Functions 代码
- 配置
package.json
- 实现后端 Java 服务接收同步事件
通过本文,您将能够搭建一个完整的系统,实现 Firebase 用户与后端数据库的实时同步。
初始化 Firebase 项目
在开始编写 Cloud Functions 之前,需要先初始化 Firebase 项目。请按照以下步骤操作:
安装 Firebase CLI
使用 Yarn 全局安装 Firebase CLI:
yarn global add firebase-tools
登录 Firebase
在终端中运行以下命令,使用您的 Google 账号登录 Firebase:
firebase login
初始化 Firebase 项目
在您的项目目录中,运行以下命令初始化 Firebase 项目:
firebase init
在初始化过程中,选择 Functions 选项,并根据提示完成配置。确保选择 TypeScript 作为编程语言,以便与本文提供的代码保持一致。
部署 Cloud Functions
完成初始化后,您可以使用以下命令部署 Cloud Functions:
firebase deploy --only functions
部署完成后,Firebase 将为您提供各个函数的 URL,您可以通过这些 URL 触发相应的函数。
Cloud Functions 代码
package.json
首先,配置 package.json
文件,以管理项目的依赖和脚本。以下是一个示例配置:
{
"name": "functions",
"scripts": {
"lint": "eslint --ext .js,.ts .",
"build": "tsc",
"build:watch": "tsc --watch",
"serve": "npm run build && firebase emulators:start --only functions",
"shell": "npm run build && firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "20"
},
"main": "lib/index.js",
"dependencies": {
"@google-cloud/functions-framework": "^3.4.2",
"axios": "^1.6.7",
"firebase-admin": "^11.8.0",
"firebase-functions": "^4.3.1"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.12.0",
"@typescript-eslint/parser": "^5.12.0",
"eslint": "^8.9.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-import": "^2.25.4",
"firebase-functions-test": "^3.1.0",
"typescript": "^4.9.0"
},
"private": true
}
说明:
- scripts: 定义了常用的命令,如构建、部署和查看日志等。
- engines: 指定了 Node.js 的版本为 20。
- dependencies: 包含了运行时所需的依赖,如
firebase-admin
和firebase-functions
。 - devDependencies: 包含了开发时需要的依赖,如 TypeScript 和 ESLint。
index.ts
接下来,编写 Cloud Functions 的核心代码 index.ts
,用于处理用户的创建和删除事件,并将这些事件发送到后端 Java 服务。
import { onRequest } from "firebase-functions/v2/https";
import * as logger from "firebase-functions/logger";
import * as functions from "firebase-functions";
import * as admin from "firebase-admin";
import axios from "axios";
import { UserRecord } from "firebase-functions/lib/common/providers/identity";
// 启动 Firebase Admin SDK。
admin.initializeApp();
const url = "https://java-api.rumibot.com/api/v1/hook/authentication"; // 后端接收事件的 URL
const authorization = "xxx"; // 认证信息(如 API 密钥)
/**
* 一个简单的 HTTP 请求函数,用于测试。
*/
export const helloWorld = onRequest((request, response) => {
logger.info("Hello logs!", { structuredData: true });
response.send("Hello from Firebase!");
});
/**
* 向后端发送事件的通用函数。
* @param eventName 事件名称,如 "onCreate" 或 "onDelete"
* @param userId 用户的 UID
*/
const sendEventToBackend = async (eventName: string, userId: string) => {
const payload = {
eventName,
userId,
};
const config = {
method: "post",
url: url,
headers: {
Authorization: authorization,
"Content-Type": "application/json",
},
data: payload,
};
try {
const response = await axios(config);
logger.info("Event sent successfully", JSON.stringify(response.data));
} catch (error) {
logger.error("Error sending event", error);
}
};
/**
* 向后端发送用户创建事件。
* @param eventName 事件名称
* @param user 用户记录
*/
const sendCreateEvent = async (eventName: string, user: UserRecord) => {
const payload = {
eventName,
...user,
};
const config = {
method: "post",
url: url,
headers: {
Authorization: authorization,
"Content-Type": "application/json",
},
data: payload,
};
try {
const response = await axios(config);
logger.info("Create event sent successfully", JSON.stringify(response.data));
} catch (error) {
logger.error("Error sending create event", error);
}
};
/**
* 监听 Firebase 用户创建事件,并同步到后端。
*/
export const syncUserOnCreate = functions.auth.user().onCreate((user) => {
return sendCreateEvent("onCreate", user);
});
/**
* 监听 Firebase 用户删除事件,并同步到后端。
*/
export const syncUserOnDelete = functions.auth.user().onDelete((user) => {
return sendEventToBackend("onDelete", user.uid);
});
功能说明:
- helloWorld: 一个简单的 HTTP 函数,用于测试 Firebase Functions 是否正常工作。
- sendEventToBackend: 通用的函数,用于向后端发送用户删除事件。
- sendCreateEvent: 专门用于发送用户创建事件的函数,包含了更详细的用户信息。
- syncUserOnCreate: 监听 Firebase 的用户创建事件,并调用
sendCreateEvent
将事件同步到后端。 - syncUserOnDelete: 监听 Firebase 的用户删除事件,并调用
sendEventToBackend
将事件同步到后端。
发送的数据
在将事件发送到后端时,数据采用 JSON 格式。具体发送的数据结构如下:
用户创建事件 (onCreate
)
{
"eventName": "onCreate",
"uid": "用户的 UID",
"email": "用户的邮箱",
"displayName": "用户的显示名称"
// 其他用户相关信息
}
用户删除事件 (onDelete
)
{
"eventName": "onDelete",
"userId": "用户的 UID"
}
说明:
- eventName: 事件名称,标识是用户创建还是删除。
- uid / userId: 用户的唯一标识符,用于后端进行相应的数据库操作。
- 其他字段(如用户创建事件中的邮箱、显示名称等)可以根据实际需求进行扩展。
后端代码
后端服务将接收来自 Firebase Functions 的同步事件,并根据事件类型对数据库进行相应的操作。以下是一个基于 Java 的后端实现示例。
ApiV1HookController.java
该控制器负责接收来自 Firebase 的 HTTP 请求,并调用相应的服务处理逻辑。
package com.litongjava.max.blog.controller;
import com.alibaba.fastjson2.JSONObject;
import com.litongjava.annotation.RequestPath;
import com.litongjava.jfinal.aop.Aop;
import com.litongjava.max.blog.service.FirebaseHookService;
import com.litongjava.model.body.RespBodyVo;
import com.litongjava.tio.boot.http.TioRequestContext;
import com.litongjava.tio.http.common.HttpRequest;
import com.litongjava.tio.http.common.HttpResponse;
import com.litongjava.tio.utils.json.FastJson2Utils;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RequestPath("/api/v1/hook")
public class ApiV1HookController {
/**
* 处理来自 Firebase 的认证请求。
* @param request HTTP 请求
* @return HTTP 响应
*/
public HttpResponse authentication(HttpRequest request) {
HttpResponse response = TioRequestContext.getResponse();
String bodyString = request.getBodyString();
log.info("Received body: {}", bodyString);
// 解析 JSON 请求体
JSONObject jsonObject = FastJson2Utils.parseObject(bodyString);
String eventName = jsonObject.getString("eventName");
String uid = jsonObject.getString("userId");
// 调用服务处理逻辑
RespBodyVo bodyVo = Aop.get(FirebaseHookService.class).authentication(eventName, uid);
return response.setJson(bodyVo);
}
}
功能说明:
- authentication: 处理
/api/v1/hook/authentication
路径的 POST 请求,解析请求体中的eventName
和userId
,并调用FirebaseHookService
进行相应的处理。
FirebaseHookService.java
该服务类根据事件类型对数据库进行相应的操作,如创建或删除用户记录。
package com.litongjava.max.blog.service;
import com.litongjava.db.activerecord.Db;
import com.litongjava.db.activerecord.Row;
import com.litongjava.max.blog.consts.TableNames;
import com.litongjava.model.body.RespBodyVo;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class FirebaseHookService {
/**
* 根据事件名称和用户 ID 进行认证和处理。
* @param eventName 事件名称,如 "onCreate" 或 "onDelete"
* @param uid 用户的 UID
* @return 响应体
*/
public RespBodyVo authentication(String eventName, String uid) {
log.info("Processing event: {}, User ID: {}", eventName, uid);
if ("onCreate".equals(eventName)) {
// 检查用户是否已存在
boolean exists = Db.exists(TableNames.max_blog_users, "id", uid);
if (!exists) {
// 创建新用户记录
Row row = new Row();
row.set("id", uid);
boolean save = Db.save(TableNames.max_blog_users, row);
if (save) {
return RespBodyVo.ok();
} else {
return RespBodyVo.fail();
}
} else {
return RespBodyVo.fail("User already exists");
}
} else if ("onDelete".equals(eventName)) {
// 删除用户记录
boolean deleted = Db.deleteById(TableNames.max_blog_users, uid);
if (deleted) {
return RespBodyVo.ok();
} else {
return RespBodyVo.fail();
}
} else {
return RespBodyVo.fail("Invalid event name");
}
}
}
功能说明:
- authentication: 根据传入的
eventName
和uid
执行相应的数据库操作。- onCreate: 检查用户是否已存在,如果不存在,则在
max_blog_users
表中创建新记录。 - onDelete: 从
max_blog_users
表中删除对应的用户记录。 - 其他事件名称返回失败响应。
- onCreate: 检查用户是否已存在,如果不存在,则在
总结
通过本文的指导,您可以实现一个完整的系统,将 Firebase 用户的创建和删除事件实时同步到后端 Java 服务。这不仅有助于保持前后端数据的一致性,还为后续的用户数据分析和业务逻辑处理提供了坚实的基础。
关键步骤回顾:
- 初始化 Firebase 项目:使用 Firebase CLI 登录并初始化项目,确保 Cloud Functions 配置正确。
- 编写 Cloud Functions:编写监听用户创建和删除事件的函数,并通过 HTTP 请求将事件数据发送到后端。
- 配置
package.json
:管理项目依赖和脚本,确保项目可以顺利构建和部署。 - 实现后端服务:编写 Java 控制器和服务,接收并处理来自 Firebase 的事件,实现数据库的同步操作。
通过这些步骤,您可以轻松地将 Firebase 与后端系统集成,实现高效的用户管理和数据同步。