AWS PHP SDK 3.36 GetObject 方法抛出 SignatureDoesNotMatch 错误

AWS PHP SDK 3.36 GetObject method throwing SignatureDoesNotMatch error

我们目前无法使用 AWS PHP SDK v. 3.36 从 S3 下载对象。通过 GetObject 方法。

我们看到以下错误:

Error executing "GetObject" on "<object path>";
AWS HTTP error: Client error: `GET <object path>` resulted in a `403 Forbidden` response:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>SignatureDoesNotMatch</Code>
  <Message>The request signature we calcul (truncated...)  SignatureDoesNotMatch (client): The request signature we calculated does not match the signature you
    provided. Check your key and signing method.
    - <?xml version="1.0" encoding="UTF-8"?>
      <Error>
        <Code>SignatureDoesNotMatch</Code>
        <Message>The request signature we calculated does not match the signature you provided.
          Check your key and signing method.

<remaining message redacted>

S3 客户端设置:

public function __construct($key, $secret, $region='us-east-1') {
    $this->key = $key;
    $this->secret = $secret;
    $this->handler = new S3Client([
        'credentials' => [
            'key'    => $key,
            'secret' => $secret
        ],
        'region' =>$region,
        'version' => '2006-03-01'
    ]);
}

调用GetObject方法:

public function getFile($bucket, $sourcefile, $saveToDestination = null) {
    $getarray = array(
        'Bucket' => $bucket,
        'Key' => $sourcefile,
    );

    if ($saveToDestination) {
        $getarray['SaveAs'] = $saveToDestination;
    }

    return $this->handler->getObject($getarray);

}

对于有问题的 IAM 用户,提供了对 S3 的完全访问权限,并且上面使用的凭据已经过验证。

IAM 策略 (AmazonS3FullAccess):

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": "*"
        }
    ]
}

进行了一些挖掘,发现 this。任何一个: a) api 键不正确或

b) 请求中未提供 Content-Length header 或

c) 请求 URI 中的非 UTF-8 编码字符串值。

希望这对您有所帮助。

事实证明,在 AWS PHP SDK 的 v3 中,如果在提供的存储桶和关键参数之间存在额外的存储桶子路径,则会出现此故障。

在上面调用getFile方法的方法中添加了以下代码:

protected function getS3File($s3_bucket, $s3_key){

         /// if the bucket contains additional paths, S3 will choke
         if (strpos($s3_bucket, '/')!==false){
             $paths = explode('/', $s3_bucket);
             $s3_bucket = array_shift($paths);

             /// so prepend them to the key!
             $s3_key=implode('/', $paths) .'/'.$s3_key;
         }

         return $this->makeTempFile($this->s3Handler->getFileContents($s3_bucket, $s3_key));
      }