使用 .net api 更新 google 云存储对象元数据因禁止错误而失败
Update google cloud storage object meta with .net api failed with forbidden error
我正在尝试使用 .net 客户端更新现有 google 云存储对象的元数据。但是,我总是遇到 Fobidden 错误。错误信息是:
Google.Apis.Requests.RequestError
Forbidden [403]
Errors [
Message[Forbidden] Location[ - ] Reason[forbidden] Domain[global]
]
我使用的代码是:
private void UpdateMeta(string key)
{
var service = Connect();
var req = service.Objects.Get(bucketName, key);
GCSObject readobj = req.Execute();
readobj.Bucket = bucketName;
if (readobj.Metadata == null)
{
readobj.Metadata = new Dictionary<string, string>();
}
readobj.Metadata["x-goog-meta-test"] = DateTime.Now.ToString();
service.Objects.Patch(readobj, readobj.Bucket, key).Execute();
}
我的代码有问题吗?
连接方法是:
private StorageService Connect()
{
string serviceAccountEmail = "account_id@developer.gserviceaccount.com";
var certificate = GetGCSCertificate(); // retrive the x509 certificate file
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { StorageService.Scope.DevstorageReadWrite }
}.FromCertificate(certificate));
var service = new StorageService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "GCS Sample",
});
return service;
}
这里是gsutil命令发送的http请求。它成功更新了元数据。
PATCH https://www.googleapis.com/storage/v1/b/BUCKETNAME/o/OBJECTNAME?ifMetagenerationMatch=1&ifGenerationMatch=1429863183870000&projection=full&prettyPrint=True&alt=json HTTP/1.1
Host: www.googleapis.com
Content-length: 128
Accept-encoding: gzip, deflate
Accept: application/json
User-agent: apitools gsutil/4.11 (win32)
Content-type: application/json
Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
{"generation": "1429863183870000", "metageneration": "1", "metadata": {"test": "2015- sdf2", "key2": "4/24/2015 8:12:58 AM"}}
这里是c#客户端发送的http请求。失败了。
PATCH https://www.googleapis.com/storage/v1/b/BUCKETNAME/o/OBJECTNAME?ifMetagenerationMatch=2&ifGenerationMatch=1429863183870000&projection=full&prettyPrint=True HTTP/1.1
User-Agent: GCS Sample google-api-dotnet-client/1.9.0.26010 (gzip)
Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json; charset=utf-8
Host: www.googleapis.com
Content-Length: 116
Accept-Encoding: gzip
{"generation":1429863183870000,"metadata":{"key2":"4/24/2015 8:23:52 AM","test":"2015- sdf2"},"metageneration":2}
我看不出这两个 http 请求有什么区别。
我找出了禁止错误的根本原因。这是因为我使用了错误的范围设置。在 Connect 方法中,而不是
Scopes = new[] { StorageService.Scope.DevstorageReadWrite }
我们应该使用
Scopes = new[] { StorageService.Scope.DevstorageFullControl }
您确定您的应用程序对该对象具有读取权限吗?您可以定义两种类型的 ACL:存储桶和对象。要读取一个对象,您需要该对象的读取权限。要列出存储桶中的对象,您需要对存储桶具有读取权限。
该代码看起来不错,但我看不出您是如何验证您的请求的。如果您的呼叫是匿名进行的,则访问私有对象将失败。要了解如何授权您的请求,请尝试 https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth
还要考虑 Shobhit 的回答。无论您使用哪个帐户读取对象,都必须具有该对象的读取权限。允许公开访问一个对象,在这种情况下,匿名用户可以阅读它。
我正在尝试使用 .net 客户端更新现有 google 云存储对象的元数据。但是,我总是遇到 Fobidden 错误。错误信息是:
Google.Apis.Requests.RequestError
Forbidden [403]
Errors [
Message[Forbidden] Location[ - ] Reason[forbidden] Domain[global]
]
我使用的代码是:
private void UpdateMeta(string key)
{
var service = Connect();
var req = service.Objects.Get(bucketName, key);
GCSObject readobj = req.Execute();
readobj.Bucket = bucketName;
if (readobj.Metadata == null)
{
readobj.Metadata = new Dictionary<string, string>();
}
readobj.Metadata["x-goog-meta-test"] = DateTime.Now.ToString();
service.Objects.Patch(readobj, readobj.Bucket, key).Execute();
}
我的代码有问题吗?
连接方法是:
private StorageService Connect()
{
string serviceAccountEmail = "account_id@developer.gserviceaccount.com";
var certificate = GetGCSCertificate(); // retrive the x509 certificate file
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { StorageService.Scope.DevstorageReadWrite }
}.FromCertificate(certificate));
var service = new StorageService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "GCS Sample",
});
return service;
}
这里是gsutil命令发送的http请求。它成功更新了元数据。
PATCH https://www.googleapis.com/storage/v1/b/BUCKETNAME/o/OBJECTNAME?ifMetagenerationMatch=1&ifGenerationMatch=1429863183870000&projection=full&prettyPrint=True&alt=json HTTP/1.1
Host: www.googleapis.com
Content-length: 128
Accept-encoding: gzip, deflate
Accept: application/json
User-agent: apitools gsutil/4.11 (win32)
Content-type: application/json
Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
{"generation": "1429863183870000", "metageneration": "1", "metadata": {"test": "2015- sdf2", "key2": "4/24/2015 8:12:58 AM"}}
这里是c#客户端发送的http请求。失败了。
PATCH https://www.googleapis.com/storage/v1/b/BUCKETNAME/o/OBJECTNAME?ifMetagenerationMatch=2&ifGenerationMatch=1429863183870000&projection=full&prettyPrint=True HTTP/1.1
User-Agent: GCS Sample google-api-dotnet-client/1.9.0.26010 (gzip)
Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json; charset=utf-8
Host: www.googleapis.com
Content-Length: 116
Accept-Encoding: gzip
{"generation":1429863183870000,"metadata":{"key2":"4/24/2015 8:23:52 AM","test":"2015- sdf2"},"metageneration":2}
我看不出这两个 http 请求有什么区别。
我找出了禁止错误的根本原因。这是因为我使用了错误的范围设置。在 Connect 方法中,而不是
Scopes = new[] { StorageService.Scope.DevstorageReadWrite }
我们应该使用
Scopes = new[] { StorageService.Scope.DevstorageFullControl }
您确定您的应用程序对该对象具有读取权限吗?您可以定义两种类型的 ACL:存储桶和对象。要读取一个对象,您需要该对象的读取权限。要列出存储桶中的对象,您需要对存储桶具有读取权限。
该代码看起来不错,但我看不出您是如何验证您的请求的。如果您的呼叫是匿名进行的,则访问私有对象将失败。要了解如何授权您的请求,请尝试 https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth
还要考虑 Shobhit 的回答。无论您使用哪个帐户读取对象,都必须具有该对象的读取权限。允许公开访问一个对象,在这种情况下,匿名用户可以阅读它。