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

使用Firebase Admin在Python生成符合Storage规则的永久下载URL

问题描述

我正在开发一款读取Firestore数据库和Firebase Storage的Flutter应用,Firebase Storage读取规则设置为仅允许已认证用户访问。我还有一个Python脚本,负责将内容上传至Firebase Storage并更新Firestore中的相关文件URL。

上传代码片段:

def _upload_file(self, file_path: str, storage_path: str) -> str:
    blob = self.bucket.blob(storage_path)
    blob.upload_from_filename(file_path)
    return blob.public_url

但通过该代码生成的URL会返回403错误,即便是应用的已认证用户访问,甚至将Storage规则设置为允许任意读写时也是如此。

需求与尝试过的方法

我需要为上传的文件生成可存储在Firestore中、供Flutter应用访问的URL。以下是尝试过的方法及问题:

  • blob.public_url:即便用户已认证,Flutter中访问仍返回403错误。
  • generate_signed_url():URL会在7天后过期,不符合需求。
  • blob.make_public():Flutter中可正常访问,但会绕过安全规则,存在安全风险(即使规则设置为仅允许已认证用户读取,该URL也能被任意访问)。

补充信息

之前开发的Flutter应用中,直接在应用内上传的Dart代码可生成正确URL:

Future<String> uploadUserImage(File image, String uid) async {
    final String fileName = uid + ".jpg";
    final ref =
        _storage.ref().child(StorageCollections.userImages).child(fileName);
    await ref.putFile(image);
    return await ref.getDownloadURL();
  }

// 生成的URL示例:https://firebasestorage.googleapis.com/v0/b/xxxxx/o/userImages%xxxxx.jpg?alt=media&token=xxxxxx

但无法在Python中实现相同效果。

核心问题

如何在文件上传后,使用firebase_admin模块(或其他方法)获取符合Storage规则且不会过期的正确URL?


解决方案

方法1:通过元数据设置永久下载令牌(推荐)

Firebase允许为Storage对象添加永久下载令牌,生成的URL格式和Flutter中getDownloadURL()返回的一致,且受安全规则约束。修改Python上传代码即可实现:

import firebase_admin
from firebase_admin import storage
import uuid
import urllib.parse

# 初始化Firebase Admin(确保已配置服务账号密钥)
if not firebase_admin._apps:
    cred = firebase_admin.credentials.Certificate('path/to/service-account-key.json')
    firebase_admin.initialize_app(cred, {
        'storageBucket': 'your-bucket-name.appspot.com'
    })

def _upload_file(self, file_path: str, storage_path: str) -> str:
    bucket = storage.bucket()
    blob = bucket.blob(storage_path)
    blob.upload_from_filename(file_path)
    
    # 生成并设置永久下载令牌
    download_token = uuid.uuid4().hex
    blob.metadata = {'firebaseStorageDownloadTokens': download_token}
    blob.patch()  # 提交元数据修改
    
    # 构造符合规则的下载URL
    base_url = f"https://firebasestorage.googleapis.com/v0/b/{bucket.name}/o/"
    encoded_path = urllib.parse.quote(blob.name)
    return f"{base_url}{encoded_path}?alt=media&token={download_token}"

方法2:调用Firebase Storage REST API获取URL

如果元数据方法不生效,可通过Admin SDK获取权限令牌后调用REST API:

import requests
import urllib.parse
from firebase_admin import auth

def get_download_url(blob):
    # 获取Admin服务账号的ID令牌
    id_token = auth.create_custom_token('service-account-uid').decode('utf-8')
    
    # 构造API请求
    api_url = f"https://firebasestorage.googleapis.com/v0/b/{blob.bucket.name}/o/{urllib.parse.quote(blob.name)}"
    headers = {'Authorization': f'Bearer {id_token}'}
    response = requests.get(api_url, headers=headers)
    
    if response.status_code == 200:
        token = response.json()['downloadTokens']
        return f"{api_url}?alt=media&token={token}"
    else:
        raise Exception(f"获取URL失败:{response.text}")

关键说明

  • 生成的URL受Storage安全规则约束,只有已认证用户可访问,符合安全要求。
  • 下载令牌永久有效,除非手动修改blob元数据删除令牌。
  • 确保服务账号拥有storage.objects.update权限,否则无法修改元数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 18:51:07