【发布时间】:2021-07-10 12:47:16
【问题描述】:
我正在学习使用 AWS 的 PHP SDK。
我想要实现的是,当一些用户在我的网站上请求一个 .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 Creds(密钥/秘密):
$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',
'region' => 'eu-west-1',
'credentials' => $credentials,
'debug' => true
]);
现在页面正在响应这段文本:
-> 进入step init,name 'idempotency_auto_fill' ------------------------- -------------- 命令设置为 array(3) { ["instance"]=> string(32) "044155c203a162626f000d004ff45d46" ["name"]=> string(11) "ListBuckets " ["params"]=> array(2) { ["@http"]=> array(1) { ["debug"]=> resource(4) of type (stream) } ["@context"]= > array(0) { } } } 请求设置为 array(0) { } -> 进入 step init,名称 's3.ssec' -------------------- ------------------ 没有变化 -> 进入步骤初始化,名称 's3.source_file' ------------------ -------------------------- 无变化 -> 进入 step init,名称 's3.save_as' ---------- ------------------------------ 没有变化 -> 进入步骤初始化,名称 's3.location' ------ ----------------------------------- 无变化 -> 进入 step init,名称为 's3.auto_encode' - ------------------------------------------------------- 无变化 -> 进入 step init , 名称 '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" } -> 进入步骤sign, name '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] }
我编辑了一些值,但来自亚马逊,这个错误与什么有关? 好像是签名错误
编辑 3:
正如我所说,这似乎是一个签名错误,我已经比较了两块代码,一个来自浏览器,另一个来自终端,浏览器请求就停止了。
Entering step sign, name 'signer'
我如何才能像在 ec2 实例中使用终端时那样进行签名(通过浏览器)?
编辑 4: 我进行了很多管理和搜索,发现我应该使用预签名 URL。 使用以下代码,我可以授予用户 20 分钟的生命周期链接,该链接将重定向他并向他显示所有可用的存储桶。
$s3Client = new Aws\S3\S3Client([
'credentials' => $credentials,
'region' => 'eu-west-1',
'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);
我终于明白了,所以我要发布答案!
【问题讨论】:
-
500状态是你的服务器还是AWS返回的?如果它是我们的服务器,那么您应该查看错误日志文件以了解详细信息。
-
@Linek 我编辑了来自 AWS 的回复。
标签: php amazon-web-services amazon-s3 request xmlhttprequest