You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Python SDK适配Firebase模拟器与Firestore安全规则?

解决Firebase模拟器中Python Admin SDK的权限拒绝问题

问题背景

你的Firestore安全规则针对user_private集合设置了严格的读取权限:

match /user_private/{uid} {
  allow read: if request.auth != null && request.auth.uid == uid;
  // 其他规则...
}

生产环境中Python Admin SDK可以正常绕过规则读取数据,但连接Firebase模拟器后,执行相同操作时出现PERMISSION_DENIED错误——原因是模拟器默认不会自动赋予Admin SDK特权,仍会严格校验安全规则。

解决方案

方案1:赋予Admin SDK模拟器管理员特权

通过自定义gRPC传输,添加模拟器专属的X-Firebase-Test头部,让请求拥有管理员权限,绕过安全规则:

from google.api_core import grpc_helpers
import grpc
from google.cloud import firestore
from google.cloud.firestore_v1 import firestore_client
from google.cloud.firestore_v1.gapic import firestore_grpc_transport
import firebase_admin
from firebase_admin import credentials, firestore

PROJECT_ID = "your-project-id"

cred = credentials.ApplicationDefault()
firebase_app = firebase_admin.initialize_app(cred, {
    'projectId': PROJECT_ID,
})
db = firestore.client(firebase_app)

# 连接Firestore模拟器
channel = grpc.insecure_channel('localhost:8080')

# 自定义传输类,添加管理员特权元数据
class AdminPrivilegeTransport(firestore_grpc_transport.FirestoreGrpcTransport):
    def __init__(self, channel):
        super().__init__(channel=channel)
    
    def _prep_request_metadata(self, request, metadata=None):
        metadata = metadata or []
        # 添加模拟器管理员特权标识
        metadata.append(('x-firebase-test', '{"skipAuth": true}'))
        return super()._prep_request_metadata(request, metadata)

# 替换客户端的内部API传输
transport = AdminPrivilegeTransport(channel=channel)
db._firestore_api_internal = firestore_client.FirestoreClient(transport=transport)

# 执行读取操作
print(
    db.collection('user_private')
    .document('abc123')
    .get()
    .to_dict()
)

方案2:模拟认证用户测试安全规则

如果需要验证安全规则的实际逻辑,而不是绕过,可以模拟指定UID的认证用户,让请求符合规则要求:

# 承接上述初始化代码...

# 自定义传输类,模拟指定UID的认证用户
class AuthenticatedUserTransport(firestore_grpc_transport.FirestoreGrpcTransport):
    def __init__(self, channel, user_uid):
        super().__init__(channel=channel)
        self.user_uid = user_uid
    
    def _prep_request_metadata(self, request, metadata=None):
        metadata = metadata or []
        # 模拟认证用户信息
        test_auth_payload = f'{{"auth": {{"uid": "{self.user_uid}"}}}}'
        metadata.append(('x-firebase-test', test_auth_payload))
        return super()._prep_request_metadata(request, metadata)

# 使用UID为abc123的模拟用户连接
transport = AuthenticatedUserTransport(channel=channel, user_uid='abc123')
db._firestore_api_internal = firestore_client.FirestoreClient(transport=transport)

# 此时读取操作会符合安全规则要求
print(
    db.collection('user_private')
    .document('abc123')
    .get()
    .to_dict()
)

方案3:临时关闭模拟器安全规则(仅快速调试用)

如果只是验证数据逻辑,无需测试规则,可以启动模拟器时直接关闭安全规则检查:

firebase emulators:start --firestore.disableSecurityRules

或者临时修改本地firestore.rules文件,添加全局允许规则(测试后务必恢复原规则):

match /{document=**} {
  allow read, write: if true;
}

说明

生产环境中Firebase Admin SDK会自动获得所有资源的访问权限,但模拟器为了还原真实规则校验逻辑,默认不会启用该特权。上述方案中,方案1适合保持Admin SDK原有特权的场景,方案2适合测试安全规则的正确性,方案3仅用于快速调试,不推荐用于规则验证环节。

内容的提问来源于stack exchange,提问作者kristina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 13:54:22