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

PHP中以Firebase应用用户身份访问Cloud Storage的实现问题

解决方案:以Firebase认证用户身份访问Cloud Storage(PHP)

你遇到的问题很典型——Firebase SDK默认用服务账号操作Storage,但很多场景下需要以应用端用户的身份来访问,我来给你几个可行的方案,从简单到SDK配置的都有:

方法1:直接调用Cloud Storage REST API(最直接)

既然你已经能通过HTTP请求或Kreait SDK拿到用户的idToken,那最简单的方式就是直接用这个token调用Cloud Storage的REST API,不需要绕SDK的复杂配置。

示例:下载文件

用Guzzle发送请求,把idToken放在Authorization头里(格式是Bearer <你的idToken>):

use GuzzleHttp\Client;

// 假设你已经通过之前的登录流程拿到了idToken
$idToken = "用户登录后得到的ID Token";
$bucketName = "your-bucket-name";
$filePath = "file_backup.txt";

$client = new Client();
$response = $client->request('GET', sprintf(
    'https://storage.googleapis.com/storage/v1/b/%s/o/%s?alt=media',
    urlencode($bucketName),
    urlencode($filePath)
), [
    'headers' => [
        'Authorization' => "Bearer {$idToken}",
    ],
    'exceptions' => false
]);

if ($response->getStatusCode() === 200) {
    $fileContent = $response->getBody()->getContents();
    print $fileContent;
} else {
    // 处理错误,比如权限不足、文件不存在等
    print $response->getBody()->getContents();
}

示例:上传文件

如果需要上传,同样用idToken做认证:

$fileContent = "要上传的内容";
$response = $client->request('POST', sprintf(
    'https://storage.googleapis.com/upload/storage/v1/b/%s/o?uploadType=media&name=%s',
    urlencode($bucketName),
    urlencode($filePath)
), [
    'headers' => [
        'Authorization' => "Bearer {$idToken}",
        'Content-Type' => 'text/plain', // 根据文件类型调整
    ],
    'body' => $fileContent
]);

方法2:修复Google Cloud Storage Client的自定义Credentials Fetcher

你之前尝试自定义FetchAuthTokenInterface的思路是对的,但可能漏了token_type参数,导致SDK无法正确识别token格式。修改你的实现:

use Google\Auth\FetchAuthTokenInterface;

class UserIdTokenFetcher implements FetchAuthTokenInterface {
    private $tokenData;

    public function __construct(string $idToken) {
        // 必须包含token_type为Bearer,否则Google Client会忽略这个token
        $this->tokenData = [
            'access_token' => $idToken,
            'token_type' => 'Bearer',
            'expires_in' => 3600 // Firebase ID Token有效期是1小时,对应3600秒
        ];
    }

    public function fetchAuthToken(callable $httpHandler = null) {
        return $this->tokenData;
    }

    public function getCacheKey() {
        return null; // 不需要缓存,因为token会过期
    }

    public function getLastReceivedToken() {
        return $this->tokenData;
    }
}

然后初始化Storage Client时,还要确保不加载默认的服务账号凭证,加上keyFile => []来禁用默认配置:

use Google\Cloud\Storage\StorageClient;

$idToken = "用户的ID Token";
$credentialsFetcher = new UserIdTokenFetcher($idToken);

$storage = new StorageClient([
    'credentialsFetcher' => $credentialsFetcher,
    'keyFile' => [], // 禁用默认的服务账号加载
    'projectId' => "你的GCP项目ID"
]);

$bucket = $storage->bucket('my_bucket');
$object = $bucket->object('file_backup.txt');
print $object->downloadAsString();

这样修改后,SDK就会用用户的ID Token来发起请求了。

方法3:结合Kreait SDK的间接方式

Kreait Firebase SDK确实没有直接提供withApplicationUser的方法,但你可以先通过SDK拿到用户的ID Token,再用上面两种方法来操作Storage:

use Kreait\Firebase\Factory;
use Kreait\Firebase\Auth;

$factory = (new Factory)->withServiceAccount(__DIR__.'/google-service-account.json');
$auth = $factory->createAuth();

// 验证用户密码,拿到用户记录和ID Token
$signInResult = $auth->signInWithEmailAndPassword($email, $password);
$idToken = $signInResult->idToken();

// 然后用这个idToken,选择方法1或方法2来操作Storage

关键注意事项

  • Firebase Storage安全规则配置:必须确保你的Storage规则允许认证用户访问,比如:
    rules_version = '2';
    service firebase.storage {
      match /b/{bucket}/o {
        match /{allPaths=**} {
          allow read, write: if request.auth != null;
        }
      }
    }
    
    更精细的规则可以根据用户UID或其他条件限制访问。
  • ID Token过期处理:Firebase ID Token有效期是1小时,你需要用登录时拿到的refresh_token来刷新token(调用https://securetoken.googleapis.com/v1/token接口),避免频繁让用户重新登录。
  • 权限范围:确保你的GCP项目中,Cloud Storage的API已经启用,并且用户的ID Token对应的账号有访问目标Bucket/文件的权限(通过Storage规则或IAM权限,优先用Storage规则更灵活)。

内容的提问来源于stack exchange,提问作者Petr 'PePa' Pavel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:07:57