调用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
相关产品推荐
相关产品推荐

