如何在删除Firestore文档时传递自定义令牌以验证安全规则
问题分析与解决方案
前端代码的错误点
- 语法错误:
getFirestore的customHeaders配置存在语法错误,多了一层冗余大括号,且content-Type首字母需大写:const db = getFirestore(app, { customHeaders: { "Content-Type": "application/json" } }) - 变量名不一致:定义了
documentToExclude,但删除操作时误用了未定义的documentToDelete,会直接导致引用错误。 - SDK方法参数错误:Firebase JS SDK的
deleteDoc方法不支持通过第二个参数传递headers配置,客户端SDK的请求不会将自定义headers传递到Firestore规则的request对象中,这是导致验证失效的核心原因。
Firestore规则的错误点
- 函数名不匹配:规则中调用了
tokenValid(),但实际定义的函数是tokenValido(),拼写不一致导致规则逻辑无法触发。 request.auth误用:request.auth仅对应Firebase Auth登录用户的认证信息,自定义header无法通过request.auth.token获取,规则里的验证逻辑完全错误。
正确实现方案
方案一:使用Firebase Auth自定义token验证(标准方案)
这是符合Firestore规则设计的官方推荐方式:
- 后端生成自定义token(基于Firebase Admin SDK):
// 后端Node.js示例 const admin = require('firebase-admin'); admin.initializeApp(); // 生成包含自定义声明的token async function generateDeleteToken() { const uid = 'temp-delete-uid'; // 可设为任意唯一标识 return admin.auth().createCustomToken(uid, { delete_token: 'delete@C0n53d3d3#' }); } - 前端用自定义token登录并执行删除:
import { initializeApp } from 'firebase/app'; import { getFirestore, doc, deleteDoc } from 'firebase/firestore'; import { getAuth, signInWithCustomToken } from 'firebase/auth'; const config = { /* 你的Firebase配置 */ }; const app = initializeApp(config); const db = getFirestore(app); const auth = getAuth(app); // 从后端接口获取自定义token const customToken = '后端返回的自定义token'; async function deleteTest() { try { // 用自定义token完成登录 await signInWithCustomToken(auth, customToken); // 修正变量名 const documentToDelete = doc(db, 'advertisers', 'vanortton1676727765248'); await deleteDoc(documentToDelete); console.log('Document deleted successfully!'); } catch (error) { console.error('Error deleting document:', error); } } deleteTest(); - 修改Firestore规则:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /advertisers/{docId} { allow read: if true; allow delete: if request.auth.token.delete_token == 'delete@C0n53d3d3#'; } } }
方案二:通过后端接口处理删除(无需Firebase Auth)
如果不想依赖Firebase Auth,可通过自有后端接口完成验证与删除:
- 后端接口(基于Firebase Admin SDK):
// 后端Node.js示例(Express框架) const admin = require('firebase-admin'); const express = require('express'); const app = express(); admin.initializeApp(); const db = admin.firestore(); app.delete('/delete-advertiser/:docId', async (req, res) => { // 从请求头获取并验证自定义token const authHeader = req.headers.authorization; if (!authHeader || authHeader !== 'Bearer delete@C0n53d3d3#') { return res.status(403).send('Invalid token'); } try { await db.collection('advertisers').doc(req.params.docId).delete(); res.status(200).send('Document deleted'); } catch (error) { res.status(500).send('Delete failed'); } }); app.listen(3000); - 前端调用后端接口:
这种方式下,Firestore规则可设置为仅允许Admin SDK访问,或保持原有规则(因删除操作由后端完成)。async function deleteTest() { try { const response = await fetch('http://你的后端地址/delete-advertiser/vanortton1676727765248', { method: 'DELETE', headers: { 'Authorization': 'Bearer delete@C0n53d3d3#' } }); if (response.ok) { console.log('Document deleted successfully!'); } else { console.error('Delete failed'); } } catch (error) { console.error('Error deleting document:', error); } } deleteTest();
内容的提问来源于stack exchange,提问作者Vanortton
相关产品推荐
相关产品推荐

