4、后端即服务(BaaS)解析:身份认证、数据库、存储、推送通知

聊到 Serverless,很多人第一反应就是函数计算。其实,后端即服务(BaaS)才是真正让前端开发者「爽到飞起」的东西。我个人的习惯是,把 BaaS 看作是 Serverless 架构的「基础设施层」——你不需要管服务器,甚至不需要管后端代码怎么写,直接调 API 就行。

这一章,咱们就拆开看看 BaaS 的几个核心能力:身份认证、数据库、存储、推送通知。这些都是我在实际项目中反复打交道的东西,踩过的坑也不少。

4.1 身份认证:别再自己写注册登录了

说实话,我早期做项目时,总喜欢自己撸一套 JWT 认证。后来发现,这玩意儿看似简单,实则坑多——密码重置、多因素认证、社交登录、Token 刷新……每一样都够你喝一壶的。

BaaS 提供的身份认证服务,说白了就是把这些脏活累活全包了。你只需要几行代码,就能搞定用户注册、登录、登出。

核心能力:
  • 邮箱/密码注册登录
  • 第三方社交登录(微信、GitHub、Google)
  • 匿名登录(适合试用场景)
  • 多因素认证(MFA)
  • 自定义 Token 策略

举个例子,用 Firebase Authentication 实现邮箱注册,代码简洁得让人感动:

// 注册新用户
firebase.auth().createUserWithEmailAndPassword(email, password)
  .then((userCredential) => {
    // 注册成功,userCredential.user 就是当前用户
    console.log('用户注册成功:', userCredential.user.uid);
  })
  .catch((error) => {
    // 错误处理,比如邮箱已存在、密码太弱
    console.error('注册失败:', error.message);
  });

// 登录
firebase.auth().signInWithEmailAndPassword(email, password)
  .then((userCredential) => {
    // 登录成功
  })
  .catch((error) => {
    // 登录失败
  });
我的经验: 记得在客户端做一次基础校验,比如密码长度、邮箱格式。虽然 BaaS 服务端也会校验,但提前拦截无效请求能省不少流量和调用次数。

4.2 数据库:实时数据同步的魔力

传统开发中,前端要拿数据,得先调后端接口,后端再查数据库,再返回。BaaS 的数据库服务直接把这个过程压缩成了「前端 ⇄ 数据库」。你想想看,这省掉了多少中间层代码?

目前主流的 BaaS 数据库分两类:

类型 代表产品 特点
文档型 Firebase Firestore、MongoDB Atlas JSON 格式存储,灵活,适合非结构化数据
关系型 Supabase(基于 PostgreSQL) 支持 SQL,适合复杂查询和事务

我个人更偏爱文档型数据库做快速原型。为什么?因为它的数据模型和前端 JavaScript 对象天然匹配,不需要 ORM 映射。

来看一个 Firestore 的读写示例:

// 写入数据
db.collection('users').doc('user-123').set({
  name: '张三',
  email: 'zhangsan@example.com',
  createdAt: firebase.firestore.FieldValue.serverTimestamp()
});

// 读取数据
db.collection('users').doc('user-123').get()
  .then((doc) => {
    if (doc.exists) {
      console.log('用户数据:', doc.data());
    }
  });

// 实时监听(这才是杀手锏)
db.collection('messages')
  .orderBy('createdAt')
  .onSnapshot((snapshot) => {
    snapshot.docChanges().forEach((change) => {
      if (change.type === 'added') {
        // 新消息来了,直接更新 UI
        renderMessage(change.doc.data());
      }
    });
  });
避坑指南: 我曾经在一个聊天项目中,没注意 Firestore 的实时监听数量限制。结果用户一多,连接数直接爆了。记住,免费层通常有并发连接上限,生产环境一定要评估好配额。

4.3 存储:文件上传没那么简单

文件存储听起来简单——不就是上传下载吗?但实际做起来,你会发现一堆问题:文件类型校验、大小限制、CDN 加速、防盗链……BaaS 的存储服务把这些全包了。

以 Firebase Storage 为例,它的安全规则是基于路径的,非常灵活:

// 安全规则示例:只允许用户上传自己的头像
service firebase.storage {
  match /b/{bucket}/o {
    match /avatars/{userId}/{fileName} {
      allow read: if true;  // 头像公开可读
      allow write: if request.auth.uid == userId;  // 只能自己写
    }
    match /documents/{document} {
      allow read, write: if request.auth != null;  // 登录用户可读写
    }
  }
}

前端上传代码也很直接:

// 上传文件
const file = fileInput.files[0];
const storageRef = firebase.storage().ref(`avatars/${userId}/${file.name}`);

const uploadTask = storageRef.put(file);

// 监听上传进度
uploadTask.on('state_changed', 
  (snapshot) => {
    const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
    console.log('上传进度:', progress + '%');
  },
  (error) => {
    console.error('上传失败:', error);
  },
  () => {
    // 上传完成,获取下载 URL
    uploadTask.snapshot.ref.getDownloadURL().then((url) => {
      console.log('文件地址:', url);
    });
  }
);
我的建议: 上传前一定要在客户端做文件类型和大小校验。虽然服务端也会拦,但用户体验上,上传半天再告诉你「文件太大」,那感觉太糟糕了。

4.4 推送通知:触达用户的最后一公里

推送通知是 BaaS 里最容易被低估的能力。很多人觉得「不就是发个通知吗」,但实际涉及的东西不少:设备 Token 管理、多平台适配(iOS/Android/Web)、通知优先级、静默推送……

BaaS 帮你封装了底层差异。你只需要关心「发给谁」和「发什么内容」。

用 Firebase Cloud Messaging(FCM)举个例子:

// 前端:获取设备 Token 并保存
const messaging = firebase.messaging();

messaging.requestPermission().then(() => {
  return messaging.getToken();
}).then((token) => {
  // 把这个 token 保存到数据库,关联到当前用户
  console.log('设备 Token:', token);
  return db.collection('users').doc(userId).update({
    fcmToken: token
  });
});

// 后端(Cloud Function):发送通知
const admin = require('firebase-admin');

exports.sendNotification = functions.firestore
  .document('messages/{messageId}')
  .onCreate(async (snap, context) => {
    const message = snap.data();
    const receiverId = message.receiverId;
    
    // 查接收者的设备 Token
    const userDoc = await admin.firestore()
      .collection('users')
      .doc(receiverId)
      .get();
    
    const token = userDoc.data().fcmToken;
    
    // 构造通知
    const payload = {
      notification: {
        title: '新消息',
        body: message.content.substring(0, 50) + '...'
      },
      token: token
    };
    
    // 发送
    return admin.messaging().send(payload);
  });
注意: 设备 Token 是会过期的!用户重装 App、清除数据后,旧 Token 就失效了。我曾经因为这个原因,给用户发了半个月的「无效通知」才发现。记得在客户端监听 Token 刷新事件,及时更新数据库。

4.5 组合使用:一个完整的用户注册流程

把这些 BaaS 服务串起来,就能构建一个完整的用户系统。我拿一个实际项目举例:

  1. 身份认证:用户用邮箱注册,BaaS 自动发验证邮件
  2. 数据库:注册成功后,在用户集合里创建一条记录,存基本信息
  3. 存储:用户上传头像,存到存储桶,URL 写回数据库
  4. 推送通知:管理员发公告时,通过 Cloud Function 触发推送

整个过程,你不需要写一行后端代码。所有的业务逻辑都在前端和云函数里完成。这就是 BaaS 的魅力——让开发者专注于产品逻辑,而不是基础设施。

总结一下:
  • 身份认证:别自己造轮子,BaaS 提供的开箱即用
  • 数据库:实时同步是杀手锏,但要注意配额和性能
  • 存储:安全规则要仔细设计,别把私密文件公开了
  • 推送通知:设备 Token 管理是重点,别忘了处理过期

嗯,这一章的内容就到这里。下一章咱们聊聊「云函数的高级模式」,包括异步处理、工作流编排和冷启动优化——这些才是真正拉开架构师水平的地方。