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

调用GCP Storage签名URL时遇元数据服务器403错误求助

问题解决:GCP Storage signUrl 触发403元数据递归调用错误

错误详情

调用signUrl生成V4签名URL时,触发以下403错误:

Caused by: java.io.IOException: Unexpected Error code 403 trying to get service accounts from Compute Engine metadata: This metadata endpoint is concealed for ?recursive calls
    at com.google.auth.oauth2.ComputeEngineCredentials.getDefaultServiceAccount(ComputeEngineCredentials.java:383)
    at com.google.auth.oauth2.ComputeEngineCredentials.getAccount(ComputeEngineCredentials.java:336)
    ... 18 common frames omitted

核心触发代码:

int ttlInMinutes = 5;
String objectName = "object-name";
String bucket = "some-bucket";
Storage storage = StorageOptions.getDefaultInstance().getService();
BlobInfo blobinfo = BlobInfo.newBuilder(BlobId.of(bucket, objectName)).build();
URL url = storage.signUrl(blobinfo, ttlInMinutes, TimeUnit.MINUTES, withV4Signature());

使用的GCP Java库版本为1.80.0。

根因分析

代码运行在依赖Compute Engine元数据凭证的环境(如GCE、GKE、Cloud Function等)时,signUrl生成V4签名需要获取服务账号信息,此时重复调用元数据服务会触发递归调用拦截机制——元数据服务禁止在已使用元数据凭证的请求中再次请求元数据,因此返回403。

解决方案

1. 显式指定服务账号密钥文件

绕过元数据服务,直接用服务账号密钥初始化Storage客户端:

// 替换为你的服务账号密钥文件路径
String serviceAccountPath = "/path/to/your/service-account-key.json";

Storage storage = StorageOptions.newBuilder()
    .setCredentials(ServiceAccountCredentials.fromStream(new FileInputStream(serviceAccountPath)))
    .build()
    .getService();

// 后续signUrl逻辑不变
BlobInfo blobinfo = BlobInfo.newBuilder(BlobId.of(bucket, objectName)).build();
URL url = storage.signUrl(blobinfo, ttlInMinutes, TimeUnit.MINUTES, withV4Signature());

2. 显式指定服务账号邮箱(GCE/GKE环境适用)

若必须使用元数据凭证,直接指定服务账号邮箱,避免客户端自动调用元数据服务获取默认账号:

String serviceAccountEmail = "your-service-account@your-project.iam.gserviceaccount.com";

Storage storage = StorageOptions.newBuilder()
    .setCredentials(ComputeEngineCredentials.newBuilder()
        .setServiceAccount(serviceAccountEmail)
        .build())
    .build()
    .getService();

// 后续signUrl逻辑不变
BlobInfo blobinfo = BlobInfo.newBuilder(BlobId.of(bucket, objectName)).build();
URL url = storage.signUrl(blobinfo, ttlInMinutes, TimeUnit.MINUTES, withV4Signature());

3. 升级GCP Java库版本

1.80.0为较旧版本,后续版本(如1.100+或2.x系列)修复了元数据递归调用的问题。以Maven为例更新依赖:

<!-- 替换为最新的google-cloud-storage版本 -->
<dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>google-cloud-storage</artifactId>
    <version>2.28.0</version>
</dependency>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 09:47:16