使用 AWS PHP SDK [S3]

问题描述

我正在学习使用 AWS 的 PHP 开发工具包。

我想要实现的是,当一些用户在我的网站上请求一个 .PHP 页面时。 example.com/listbuckets.PHP

页面应返回与我的 IAM 角色关联的存储桶。

这是我的代码

$s3Client = new S3Client([
    'profile' => 'default','region' => 'eu-west-1','version' => 'latest'
]);

//Listing all S3 Bucket
$buckets = $s3Client->listBuckets();
foreach ($buckets['Buckets'] as $bucket) {
    echo $bucket['Name'] . "\n";
}

?>


使用该代码,我可以通过 CLI 或终端成功查看我的 S3 存储桶。但是当我通过浏览器请求页面时,它显示 500 Internal Server Error。

在这里遗漏了什么?

提前致谢。

编辑: 我尝试通过以下方式传递我的 AWS 凭证(密钥/秘密):

$credentials = new Aws\Credentials\Credentials('key','secret');

$s3 = new Aws\S3\S3Client([
    'version'     => 'latest','region'      => 'eu-west-1','credentials' => $credentials
]);

如果通过网络浏览器访问,我仍然无法解析 PHP 页面,这可能是与权限/所有权相关的问题吗?如果我通过终端执行,即使我可以看到我的桶 PHP listbuckets.PHP

编辑2: 我在

上传递了一个新参数
$s3Client = new Aws\S3\S3Client([
    'version'     => 'latest','credentials' => $credentials,'debug'       => true
]);

现在页面响应了这个文本块:

-> 进入步骤init,名称为'idempotency_auto_fill' ------------------------------------- -------------- 命令设置为 array(3) { ["instance"]=> string(32) "044155c203a162626f000d004ff45d46" ["name"]=> string(11) "ListBuckets " ["params"]=> array(2) { ["@http"]=> array(1) { ["debug"]=> 类型(流)的资源(4)} ["@context"]= > array(0) { } } } request is set to array(0) { } -> 进入步骤 init,name 's3.ssec' ------------------- ------------------ 没有变化 -> 进入步骤 init,名称 's3.source_file' ------------------ -------------------------- 没有变化 -> 进入步骤 init,name 's3.save_as' ---------- ------------------------------ 没有变化 -> 进入步骤 init,name 's3.location' ------ ------------------------------------- 没有变化 -> 进入步骤 init,名称 's3.auto_encode' - --------------------------------------------- 没有变化 -> 进入步骤 init,name 's3.head_object' ------------------------------------------- - 没有变化 -> 输入步骤验证,名称 'v alidation' --------------------------------------------- 没有变化 ->进入步骤验证,名称为'input_validation_middleware' ------------------------------------------ ------------------- 没有变化 -> 进入步骤构建,名称为 'builder' ------------------- ------------------- request.instance 设置为 00fq4442000004ffw2c46 request.method 设置为 GET request.headers 设置为 array(2) { ["X-Amz- Security-Token"]=> string(7) "[TOKEN]" ["Host"]=> array(1) { [0]=> string(26) "s3.eu-west-1.amazonaws.com" request.scheme 设置为 https request.path 设置为 / -> Entering step build,name 'ApiCallMonitoringMiddleware' ------------------------ ---------------------------------- 没有变化 -> 进入步骤构建,名称 '' ----- -------------------------- request.instance 从 e33e626cc 更改为 00dw0sq03c45d46 request.headers.User-Agent 设置为 array(1) { [ 0]=> string(50) "aws-sdk-PHP/3.178.4 OS/Linux/4.19.0-16-cloud-amd64" } -> 进入步骤构建,名称 'endpoint_parameter' -- - - - - - - - - - - - - - - - - - - - - - - - - 没有变化 - > 进入步骤构建,命名为'EndpointdiscoveryMiddleware' ----------------------------------------- ----------------- 没有变化-> 进入步骤构建,名称为's3.checksum' ------------------- --------------- 没有变化 -> 进入步骤构建,名称为's3.content_type' ------------- --------------------------------- 没有变化 -> 进入步骤构建,名称为 's3.endpoint_middleware' --- --------------------------------------------------没有变化 -> 进入步骤构建,名称为 's3.bucket_endpoint_arn' -------------------- ----------------- 没有变化-> 输入步骤符号,名称为'StreamRequestPayloadMiddleware' --------------------- --------------------------------------- 没有变化 -> 输入步骤符号,名称 'invocation -id' ------------------------------------------- request.instance 已更改从 000003a1626c9002f900025d46 到 0e55j00003a1626cy004ff4r3d46 request.headers.aws-sdk-invocation-id 被设置为 array(1) { [0 ]=> string(32) "321593e23171d701cdwae9" } -> 输入步骤符号,名称'retry' ----------------------------- ------ request.instance 从 dw000qdqd04ff45d46 更改为 0400411626c4210004445d46 request.headers.aws-sdk-retry 设置为 array(1) { [0]=> string(3) "0/0" } -> 进入步骤签名,名称 'signer' ------------------------------------ request.instance 从 02z00004ss2004ff45d46 更改为 01626d000045d46 request.headers.x-amz-content-sha256 被设置为 array(1) { [0]=> string(64) "ec44298f9b934ca491b7855" } request.headers.X-Amz-Date 被设置为 array(1) { [ 0]=> string(16) "25T142413Z" } request.headers.Authorization 被设置为 array(1) { [0]=> string(211) "AWS4-HMAC-SHA256 Credential=[KEY]/20210415/eu- west-1/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date,Signature=[SIGNATURE] }

我编辑了一些值,但是来自 Amazon,这个错误与什么有关? 好像是签名错误

编辑 3: 正如我所说,这似乎是一个签名错误,我比较了两块代码,一块来自浏览器,另一块来自终端,浏览器请愿书就停在了那里。 Entering step sign,name 'signer'

当我从 ec2 实例使用我的终端时,我怎样才能(通过浏览器)签名?

编辑 4: 我管理和搜索了很多,发现我应该使用预签名 URL。 使用以下代码,我可以授予用户一个 20 分钟的生命周期链接,该链接重定向他并向他显示所有可用的存储桶。

$s3Client = new Aws\S3\S3Client([
    'credentials' => $credentials,'version' => '2006-03-01',]);

$cmd = $s3Client->getCommand('ListBuckets',[
    'Bucket' => '*'
    
]);

$request = $s3Client->createPresignedRequest($cmd,'+20 minutes');

// Get the actual presigned-url
$presignedUrl = (string)$request->getUri();
echo($presignedUrl);

编辑 5: 如果有人想打印 AWS PHP SDK 生成的 url 结果,请使用此 PHP 代码

$result = file_get_contents($presignedUrl);
echo($result);

我终于明白了,所以我要发布答案!

解决方法

将代码放在 try/catch 块中。在 catch 中打印错误信息。

您是否已经安装过 Composer?

所有在 PHP 中活动的错误输出?

,

所以整个观点是有效的,但我执行错了,我向正在学习 AWS PHP SDK 的任何人推荐此 article,以便他/她可以更好地理解从浏览器制作预签名网址的概念/客户。


让我们分解问题, 场景是,当有人请求我的 listbuckets.php 页面时,该页面应该打印出我所有的 S3 存储桶。好的。

需要的东西: 1- AWS 账户 2- EC2 实例 3- S3 存储桶 4- 通过 SSH 访问 EC2 5- EC2 上的作曲家 6- AWS PHP SDK 安装在您的网络项目的根目录上。

当您拥有所有这些东西后,如果您想从任何对 AWS 资源有效的用户发出匿名请求,您应该使用 presigned-urls

转到您的listbuckets.php

代码:


//Key and Secret are variables that you get from your IAM Acces Management
$credentials = new Aws\Credentials\Credentials('KEY','SECRET');

//Create an S3 Client to communicate with AWS.
$s3Client = new Aws\S3\S3Client([
    'credentials' => $credentials,'region' => 'eu-west-1','version' => '2006-03-01',]);

//Here we specify the command that we want to execute on our AWS resource.
//ListBuckets,Put object... 
//We tell with * to List **all** the buckets
$cmd = $s3Client->getCommand('ListBuckets',[
    'Bucket' => '*'
    
]);

//We make the request,including the command we want to execute and the lifespan //of the url. It will be available only 20min,10min... Whatever you want.
$request = $s3Client->createPresignedRequest($cmd,'+20 minutes');

// Get the actual presigned-url,with this URL can make the request to AWS and it will be valid,we will be requesting AWS to LIST ALL my S3 buckets.
$presignedUrl = (string)$request->getUri();
echo($presignedUrl . "<br>");
echo "<br>";


//What we are going to get,is an XML file,from that file we want (in my case) //the name only so...
$xml = simplexml_load_file($presignedUrl);
//echo $xml->Buckets->Bucket->Name; 
foreach ($xml->Buckets->Bucket as $namee)
{

    echo $namee->Name . "\n";
}


有了这段代码,每次有人询问listbucket.php,在后台,它都会向aws生成一个有效的请求,并打印出该请求的响应名称。

就是这样:)