5

我觉得在这里发布这个很奇怪,但因为SO是Google API支持的唯一官方渠道,所以我想我需要在这里提问。为什么Google Storage API不能与Amazon SDK v3一起使用?

如果你有API,工具的使用,或其他软件开发相关的 问题,搜索和发布问题上堆栈溢出,使用 官方谷歌云存储标签。

好吧,所以这里。我花了两天的精力在尝试让Google Storage在亚马逊PHP SDK的v3版本(最新版本)上工作。我无法使用较旧版本的SDK,因为我试图坚持使用Laravel 5.1的文件系统,而无需为Google Storage编写全新的驱动程序。我相信这是一个什么样谷歌发布了谷歌存储的精神内:

https://cloud.google.com/storage/docs/migrating

在从Amazon S3到谷歌云存储的简单迁移,您可以 使用现有的工具和库用于生成已认证的 对Amazon S3的REST请求,还将已验证的请求发送至 Google云端存储。本部分描述了您需要对现有的 工具和库进行的更改。

若要设立一个简单的迁移执行以下操作:

设置默认的谷歌项目。

获取开发人员密钥。

在您现有的工具或库中,进行以下更改:将请求 端点更改为使用Google Cloud Storage请求端点。将 Amazon Web Services(AWS)访问和密钥替换为相应的 Google Cloud Storage访问密钥和密钥(统称为 您的Google开发人员密钥)。

就是这样!此时,您可以使用现有工具和库开始 向Google云端存储发送keyed-hash消息 认证码(HMAC)请求。

什么样的音调!让我们尝试使用使用gsutil的互操作性凭证。

$client = new S3Client([ 
    'credentials' => [ 
     'key' => 'GOOGxxxxxxxxxxxxxxx', 
     'secret' => 'ZfcOTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 
    ], 
    'region' => 'US', 
    'version' => 'latest', 
    'endpoint' => 'https://storage.googleapis.com', 
]); 

try { 
    $result = $client->putObject(array(
     'Bucket' => 'devtest', 
     'Key' => 'test', 
     'Body' => 'Hello world' 
    )); 

    echo $result['ObjectURL']; 
} catch (\Aws\S3\Exception\S3Exception $e) { 
    // The AWS error code (e.g.,) 
    echo $e->getAwsErrorCode() . "\n"; 
    // The bucket couldn't be created 
    echo $e->getMessage() . "\n"; 
} 

不起作用。您会收到“错误的身份验证标题”。我们来看看这个标题。

AWS4-HMAC-SHA256 凭证= GOOGGUxxxxxxxxxxx/20150611/US/S3/aws4_request, SignedHeaders =主机; X-AMZ-内容-SHA256; X-AMZ-日期, 签名= 9c7de4xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

我在这里创建了一个关于此的SO帖子,有人建议我添加'signature'=>'v2'。

Google Storage Incorrect Authorization Header with Amazon S3 PHP SDK v3

让我们试试:

$client = new S3Client([ 
    'credentials' => [ 
     'key' => 'GOOGxxxxxxxxxxxxxxx', 
     'secret' => 'ZfcOTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 
    ], 
    'region' => 'US', 
    'version' => 'latest', 
    'endpoint' => 'https://storage.googleapis.com', 
    'signature' => 'v2', 
]); 

没有运气。同样的错误。授权标头没有改变。让我们看看S3Client的代码,看看如何使用“签名”:

public function createPresignedRequest(CommandInterface $command, $expires) 
{ 
    /** @var \Aws\Signature\SignatureInterface $signer */ 
    $signer = call_user_func(
     $this->getSignatureProvider(), 
     $this->getConfig('signature_version'), 
     $this->getApi()->getSigningName(), 
     $this->getRegion() 
    ); 

    return $signer->presign(
     \Aws\serialize($command), 
     $this->getCredentials()->wait(), 
     $expires 
    ); 
} 

它没有。所以,现在我们从S3的官方文档偏离,因为他们说同一件事:

http://docs.aws.amazon.com/aws-sdk-php/guide/latest/configuration.html

这不是“签名”,这是“signature_version”。让我们将其改为v2。

$client = new S3Client([ 
    'credentials' => [ 
     'key' => 'GOOGxxxxxxxxxxxxxxx', 
     'secret' => 'ZfcOTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 
    ], 
    'region' => 'US', 
    'version' => 'latest', 
    'endpoint' => 'https://storage.googleapis.com', 
    'signature_version' => 'v2', 
]); 

这次至少我们得到了一个不同的错误!

UnresolvedSignatureException在SignatureProvider.php线61:无法 解决的V2/S3/US签名。有效签名版本包括 v4和匿名。

因此,在玩了两天之后,看起来这是不可能的,至少不会让Google想让你相信他们的音调。我根本无法得到这个工作,所以我希望这里有人能够阐明这一点。要么我错过了一些重要的事情,要么谷歌虚假宣传谷歌存储使用亚马逊的S3 SDK工作,并浪费开发者的时间。我在想,也许我们必须手动劫持授权头,但那不在我的专业知识范围之内。任何帮助将不胜感激。

+0

将'version'设置为早于'latest',怎么办?没有尝试,只是在黑暗中拍摄。 – zaak

+0

@zaak是的,我也试过。没有运气。 – Citizen

+0

您可以比较gsutil auth头文件(可以用“gsutil -D ...”查看)与PHP SDK发送的不同吗? –

回答

3

因此,我打算发布的时间比从未晚,并说我使用laravel 5.1,您必须在配置时选择是否要使用AWS或GCS,因为您无法进行配置安装两个版本的aws php客户端(这限制你选择的flysystem为v2或v3,GCS需要v2,而laravel中的s3实现需要v3,我花了小时试图让v3与GCS协同工作,但认证标头是不同的,所以我没有理会。

你必须提供自己的供应商,但它并不难设置,只需在应用程序创建GcsAppsServiceProvider.php /供应商

<?php namespace App\Providers; 

use Illuminate\Support\ServiceProvider; 
use Storage; 
use Aws\S3\S3Client; 
use League\Flysystem\AwsS3v2\AwsS3Adapter; 
use League\Flysystem\Filesystem; 

class GcsAppsServiceProvider extends ServiceProvider 
{ 
    public function register() 
    { 

    } 

    public function boot() 
    { 
     Storage::extend('gcs', function($app, $config) 
     { 
      $client = S3Client::factory([ 
       'key' => $config['key'], 
       'secret' => $config['secret'], 
       'base_url' => $config['base_url'], 
      ]); 

      return new Filesystem(new AwsS3Adapter($client, $config['bucket'])); 
     }); 
    } 
} 

基本上在你的配置你只是复制S3配置在filesystem.php和不断变化的区域 - > BASE_URL。您也可以自由将默认和云更改为gcs以支持谷歌云存储。

's3' => [ 
    'driver' => 's3', 
    'key' => env('AWS_KEY', 'your-key'), 
    'secret' => env('AWS_SECRET', 'your-secret'), 
    'region' => env('AWS_REGION','your-region'), 
    'bucket' => env('AWS_BUCKET','your-bucket'), 
], 

'gcs' => [ 
    'driver' => 'gcs', 
    'key' => env('GCS_KEY', 'your-key'), 
    'secret' => env('GCS_SECRET', 'your-secret'), 
    'base_url' => env('GCS_BASE_URL','your-base-url'), 
    'bucket' => env('GCS_BUCKET','your-bucket'), 
], 

最后但并非最不重要,你还需要将提供程序添加到提供者列表中app.php

'providers' => [ 
    ... 
    App\Providers\GcsAppsServiceProvider::class, 
], 

AWS的S3适配器还提到,GCS supports it in their documentation

相关问题