Php 浏览器上载到具有实例角色的s3

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>

这是我关于使用实例配置文件签名的策略文档的后续内容

我正在开发一个系统,允许直接拖放上传到S3存储桶;首先向我的服务器发出包含文件元数据的AJAX请求。验证后,我的服务器将使用用于完成上载的表单参数进行响应

建立基于浏览器的上传的过程已经很好地解释过了,并且在我的本地测试环境中一切都正常

但是,一旦我的应用程序部署到EC2实例上,当浏览器尝试上载文件时,我会看到以下错误:

<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天了,我仍在努力工作