我们希望从我们的应用服务器中的Google Storage下载文件.对单个存储桶进行只读限制访问非常重要.
起初我使用了一个常规用户帐户(不是服务帐户),它有权访问我们的Google Cloud项目中的所有存储桶,一切正常 - 我的Java代码打开存储桶并下载文件没有问题.
Storage storage = StorageOptions.getDefaultInstance().getService();
Bucket b = storage.get( "mybucketname" );
Run Code Online (Sandbox Code Playgroud)
然后我想切换到使用专门创建的服务帐户,该帐户只能访问一个存储桶.所以我创建了一个服务帐户,授予读取单个存储桶的权限,并下载了其密钥文件.Google Cloud Console中的权限命名为:
存储对象查看器(3个成员)读取对GCS对象的访问权限.
gsutil命令行实用程序可以正常使用此帐户 - 从命令行可以访问此存储桶但不能访问其他存储桶.
使用以下命令从命令行初始化:
gcloud --project myprojectname auth activate-service-account files-viewer2@myprojectname.iam.gserviceaccount.com --key-file=/.../keyfilename.json
Run Code Online (Sandbox Code Playgroud)
我甚至尝试了两个可以访问不同存储桶的不同服务帐户,从命令行我可以在它们之间切换,gsutil只能访问相关的存储桶,而对于任何其他存储器,它都会返回错误:
"AccessDeniedException:403 Caller没有对bucket xxxxxxxxxx的storage.objects.list访问权限."
所以,从命令行一切正常.但在Java中,身份验证存在一些问题.
我以前与常规用户帐户一起使用的默认身份验证停止工作 - 它报告错误:
com.google.cloud.storage.StorageException:匿名用户没有对bucket xxxxxxxxxx的storage.buckets.get访问权限.
然后我尝试了以下代码(这是最简单的变体,因为它依赖于关键的json文件,但我已经尝试了在各种论坛中找到的许多其他变体,但没有成功):
FileInputStream fis = new FileInputStream( "/path/to/the/key-file.json" );
ServiceAccountCredentials credentials = ServiceAccountCredentials.fromStream( fis );
Storage storage = StorageOptions.newBuilder().setCredentials( credentials )
.setProjectId( "myprojectid" ).build().getService();
Bucket b = storage.get( "mybucketname" );
Run Code Online (Sandbox Code Playgroud)
而我收到的只是这个错误:
com.google.cloud.storage.StorageException:调用者没有对bucket mybucketname的storage.buckets.get访问权限.原因:com.google.api.client.googleapis.json.GoogleJsonResponseException:403 Forbidden
无论我尝试访问哪些存储桶(甚至不存在),都会返回相同的错误.令我困惑的是,使用相同的JSON密钥文件初始化的相同服务帐户在命令行中运行良好.所以我认为Java代码中缺少某些东西来确保正确的身份验证.