Php 浏览器上载到具有实例角色的s3
这是我关于使用实例配置文件签名的策略文档的后续内容 我正在开发一个系统,允许直接拖放上传到S3存储桶;首先向我的服务器发出包含文件元数据的AJAX请求。验证后,我的服务器将使用用于完成上载的表单参数进行响应 建立基于浏览器的上传的过程已经很好地解释过了,并且在我的本地测试环境中一切都正常 但是,一旦我的应用程序部署到EC2实例上,当浏览器尝试上载文件时,我会看到以下错误:Php 浏览器上载到具有实例角色的s3,php,file-upload,amazon-web-services,amazon-s3,amazon-ec2,Php,File Upload,Amazon Web Services,Amazon S3,Amazon Ec2,这是我关于使用实例配置文件签名的策略文档的后续内容 我正在开发一个系统,允许直接拖放上传到S3存储桶;首先向我的服务器发出包含文件元数据的AJAX请求。验证后,我的服务器将使用用于完成上载的表单参数进行响应 建立基于浏览器的上传的过程已经很好地解释过了,并且在我的本地测试环境中一切都正常 但是,一旦我的应用程序部署到EC2实例上,当浏览器尝试上载文件时,我会看到以下错误: <Error> <Code>InvalidAccessKeyId</Code>
<Error>
<Code>InvalidAccessKeyId</Code>
<Message>The AWS Access Key Id you provided does not exist in our records.</Message>
<RequestId>...</RequestId>
<HostId>...</HostId>
<AWSAccessKeyId>ASIAxxxyyyzzz</AWSAccessKeyId>
</Error>
这里的ASIAxxxyyyzzz
值来自从元数据服务获得的实例角色凭据;这些凭证似乎不能在EC2之外用于促进基于浏览器的上传
我还研究了如何通过执行以下操作生成另一组临时凭据:
$token = $sts->assumeRole(array(
'RoleArn' => 'arn:aws:iam::xyz:role/mydomain.com',
'RoleSessionName' => 'uploader',
));
$credentials = new Credentials($token['Credentials']['AccessKeyId'], $token['Credentials']['SecretAccessKey']);
这个调用为我提供了一组新的凭据,但当我使用它时,它给出了与上面相同的错误
我希望有人曾经这样做过,并且可以告诉我我错过了什么愚蠢的事情:)AWS文档在这方面非常混乱,但我怀疑您需要在S3上传POST请求中包含
x-amz-security-token
参数,并且它的值与您从STS($token>获得的SessionToken
匹配['Credentials']['SessionToken']
)
STS临时凭据仅在包含相应的安全令牌时有效
缔约国指出:
使用Amazon DevPay的每个请求都需要两个x-amz-security-token
表单字段:一个用于产品令牌,一个用于用户令牌
但是该参数也在DevPay之外使用,用于传递STS令牌,您只需要在表单字段中传递一次。正如所指出的,当您使用临时凭据时,会话令牌需要传递给您正在使用的服务。其中提到了x-amz-security-token
字段,但似乎表明它是o仅用于DevPay;这可能是因为DevPay使用相同类型的临时凭据,因此需要会话安全令牌
2013-10-16:亚马逊已经更新了他们的文档,使这一点更加明显
事实证明,甚至不需要使用STS;元数据服务接收的凭据也带有这样的会话令牌。当SDK与临时凭据一起使用时,此令牌会自动为您传递,但在这种情况下,最终请求是由浏览器发出的,因此需要显式传递
以下是我的工作代码:
$credentials = Credentials::factory();
$signer = new S3Signature();
$policy = new AwsUploadPolicy(new DateTime('+1 hour', new DateTimeZone('UTC')));
$policy->setBucket('upload.mydomain.com');
$policy->setACL($policy::ACL_PUBLIC_READ);
$policy->setKey('uploads/test.jpg');
$policy->setContentType('image/jpeg');
$policy->setContentLength(5034);
$fields = array(
'AWSAccessKeyId' => $credentials->getAccessKeyId(),
'key' => $path,
'Content-Type' => $type,
'acl' => $policy::ACL_PUBLIC_READ,
'policy' => $policy,
);
if ($credentials->getSecurityToken()) {
// pass security token
$fields['x-amz-security-token'] = $credentials->getSecurityToken();
$policy->setSecurityToken($credentials->getSecurityToken());
}
$fields['signature'] = $signer->signString($policy, $credentials);
我正在使用一个helper类来构建策略,名为;在编写本文时,它还不完整,但它可能会帮助其他有类似问题的人
权限是最后一个问题;我的代码将ACL设置为public read
,这样做需要额外的s3:PutObjectAcl
权限
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:PutObject",
"s3:PutObjectAcl"
],
"Sid": "Stmt1379546195000",
"Resource": [
"arn:aws:s3:::upload.mydomain.com/uploads/*"
],
"Effect": "Allow"
}
]
}
好的,这似乎是合理的。让我今晚把它激发起来,看看它是如何进行的:)我已经更接近它了;它不再抱怨未知的访问id,但现在它给出了一个“拒绝访问”错误:(嗯……试着在IAM中给它
s3:PutObjectAcl
权限,看看它是否有帮助。这样做了。我稍后会接受我自己的回答,但你提供了我还没有尝试过的东西,这是你的赏金:)谢谢!嗨,杰克,你能不能只使用临时凭证发布你关于上传到s3的工作。我很难弄清楚这一点。T__T@WonderingCoder上传本身不是在PHP中进行的;它是在JavaScript中完成的,并使用FormData
类(对于支持它的浏览器)还有CORS。这是你想了解更多的部分吗?嗨,谢谢你的回复。请看我的帖子,我也在使用临时凭证。我们唯一的主要区别是你使用了SDK:。已经4天了,我仍在努力工作