NodeJs与React搭配Firebase auth时如何保护NodeJS API端点?
解决方案
核心逻辑说明
你不需要自行在后端生成JWT,Firebase Authentication在前端完成用户登录后,会自动为当前登录用户签发ID Token,这本身就是符合标准的JWT,你直接用这个Token做接口校验即可。
具体实现步骤
第一步:React前端请求时携带Firebase ID Token
每次调用后端接口前,先从Firebase Auth实例中获取当前用户的ID Token,放到请求头里携带。
示例代码(React端):
import { getAuth, getIdToken } from "firebase/auth"; // 封装带身份认证的请求方法 const requestWithAuth = async (url, options = {}) => { const auth = getAuth(); const user = auth.currentUser; if (!user) throw new Error("用户未登录"); // 获取最新的ID Token,SDK会自动刷新过期的Token const idToken = await getIdToken(user); // 把Token放到Authorization请求头 const res = await fetch(url, { ...options, headers: { ...options.headers, Authorization: `Bearer ${idToken}` } }); return res.json(); }; // 调用示例:获取select组件选项 const loadOptions = async () => { const options = await requestWithAuth("/api/get-select-options"); // 处理返回的选项数据 };
第二步:Express后端编写Token校验中间件
你需要在后端集成Firebase Admin SDK,用来校验前端传过来的ID Token的合法性,校验通过才允许访问接口。
首先安装依赖:
npm install firebase-admin
然后初始化Firebase Admin,编写校验中间件:
const admin = require("firebase-admin"); // 初始化Firebase Admin,服务账号密钥可从Firebase控制台下载 const serviceAccount = require("./path/to/serviceAccountKey.json"); admin.initializeApp({ credential: admin.credential.cert(serviceAccount) }); // 认证校验中间件 const authMiddleware = async (req, res, next) => { const authHeader = req.headers.authorization; // 没有携带Token直接返回401 if (!authHeader || !authHeader.startsWith("Bearer ")) { return res.status(401).send("未授权访问"); } const idToken = authHeader.split("Bearer ")[1]; try { // 校验Token合法性,会自动校验签名、过期时间、签发方等核心信息 const decodedToken = await admin.auth().verifyIdToken(idToken); // 把解析出来的用户信息挂载到req对象,后续接口可以直接使用 req.user = decodedToken; next(); } catch (error) { return res.status(401).send("Token无效或已过期"); } };
第三步:给需要保护的接口加上校验中间件
// 不需要鉴权的公开接口可以直接定义 app.get("/api/public", (req, res) => { res.send("公开内容"); }); // 需要鉴权的接口加上authMiddleware中间件 app.get("/api/get-select-options", authMiddleware, (req, res) => { // 可以通过req.user.uid获取当前用户的唯一标识,做细粒度权限控制 const userId = req.user.uid; // 查询数据库返回对应数据 res.json([{label: "选项1", value: 1}, {label: "选项2", value: 2}]); }); app.post("/api/save-data", authMiddleware, (req, res) => { const userId = req.user.uid; const postData = req.body; // 写入数据库时可以关联用户ID,避免越权操作 res.send("保存成功"); });
额外安全优化建议
- 所有接口必须开启HTTPS,避免Token在传输过程中被窃取
- 涉及写入、修改、删除的操作,除了Token校验之外,还要做业务权限校验,比如确认当前用户是否有权限操作对应的数据
- CORS配置只允许你自己的前端域名访问后端接口,避免跨域恶意调用
内容的提问来源于stack exchange,提问作者user16317357
相关产品推荐
相关产品推荐

