简体   繁体   English

AWS Amazon Cloudfront PHP的签名URL

[英]signed url for AWS Amazon Cloudfront PHP

I'm trying to serve time-limited links to private content on a Cloudfront-enabled Amazon S3 bucket. 我正在尝试为支持Cloudfront的Amazon S3存储桶上的私有内容提供有时间限制的链接。

I would like to be able to use the AWS PHP API 我希望能够使用AWS PHP API

$credentials = array("key" => $variables->strAmazonAccessKey, "secret" => $variables->strAmazonSecretKey);
$s3 = new AmazonS3($credentials);
$cdn = new AmazonCloudFront($credentials);

$cdn->set_keypair_id($variables->cdn_keypair_id);
$cdn->set_private_key($variables->cdn_private_key);

$response = $s3->set_object_acl($bucket, $obj, AmazonS3::ACL_OWNER_FULL_CONTROL);
return htmlspecialchars($cdn->get_private_object_url($cloudfront_id, $obj, '1 day'));

But I keep getting this access denied message 但我一直收到这个拒绝访问的消息

<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>BD2B4CE946ED67C4</RequestId>
<HostId>
JrBu9+HqhGwzRA4ILFeT2SGyp5nXEY/RrYWQDz2dzdWDIRTgVy2i3Llm460ok99M
</HostId>
</Error>

The cdn_private_key is a string containing the RSA private key which looks sort of like this: cdn_private_key是一个包含RSA私钥的字符串,看起来像这样:

-----BEGIN RSA PRIVATE KEY-----
ldflsjhflasdkjfhlvbdslvahsdlviwuheliuhvlhlvweljbsdvljkbsadvlkjsd
ldflsjhflasdkjfhlvbdslvahsdlviwuheliuhvlhlvweljbsdvljkbsadvlkjsd
ldflsjhflasdkjfhlvbdslvahsdlviwuheliuhvlhlvweljbsdvljkbsadvlkjsd
ldflsjhflasdkjfhlvbdslvahsdlviwuheliuhvlhlvweljbsdvljkbsadvlkjsd
ldflsjhflasdkjfhlvbdslvahsdlviwuheliuhvlhlvweljbsdvljkbsadvlkjsd
ldflsjhflasdkjfhlvbdslvahsdlviwuheliuhvlhlvweljbsdvljkbsadvlkjsd
ldflsjhflasdkjfhlvbdslvahsdlviwuheliuhvlhlvweljbsdvljkbsadvlkjsd
ldflsjhflasdkjfhlvbdslvahsdlviwuheliuhvlhlvweljbsdvljkbsadvlkjsd
ldflsjhflasdkjfhlvbdslvahsdlviwuheliuhvlhlvweljbsdvljkbsadvlkjsd
ldflsjhflasdkjfhlvbdslvahsdlviwuheliuhvlhlvweljbsdvljkbsadvlkjsd
ldflsjhflasdkjfhlvbdslvahsdlviwuheliuhvlhlvweljbsdvljkbsadvlkjsd
ldflsjhflasdkjfhlvbdslvahsdlviwuheliuhvlhlvweljbsdvljkbsadvlkjsd
ldflsjhflasdkjfhlvbdslvahsdlviwuheliuhvlhlv=
-----END RSA PRIVATE KEY-----

I may be doing something wrong there, but I would've expected to get an error about the key or signature instead of an access denied message. 我可能在那里做错了,但我希望得到关于密钥或签名的错误而不是访问被拒绝的消息。

I have also tried manually signing using the following method, but get the same error, only with different HostId and RequestId: 我也尝试使用以下方法手动签名,但只有不同的HostId和RequestId才能得到相同的错误:

$accessId = $variables->cdn_keypair_id;
$priv_key = $variables->cdn_private_key;
$resource = 'https://'. $cloudfront_id .'/' . $obj;

$expires = time() + 3600*24; 
$to_sign = '{"Statement":[{"Resource":"'.$resource.'","Condition":{"DateLessThan":{"AWS:EpochTime":'.$expires.'}}}]}';     

$signature = '*Signature will go here*'; 
$pkeyid = openssl_get_privatekey($priv_key); 
if (openssl_sign( $to_sign, $signature, $pkeyid, OPENSSL_ALGO_SHA1)) { 
    $signature = urlencode( base64_encode( $signature ) ); 
} 
return ($resource.'?Key-Pair-Id='.$accessId.'&Expires='.$expires.'&Signature='.$signature); 

I've eventually solved the problem. 我最终解决了这个问题。

It seems that Amazon aren't very clear about this ... hidden deep in the bowels of AWS documentation you are instructed to set the bucket permissions on the S3 bucket to allow CloudFront access to it. 似乎亚马逊对此并不十分清楚......隐藏在AWS文档的内容深处,您被指示在S3存储桶上设置存储桶权限以允许CloudFront访问它。

Further confusion ensues when you have to set the Principal property on the policy, as it suggests you need to get the Canonical User ID. 当您必须在策略上设置Principal属性时,会出现进一步的混淆,因为它建议您需要获取Canonical用户ID。 However, this is NOT the Canonical User ID for your AWS account found on the Security Credentials page .. it is instead found in the "Origin Access Identity" link on the CloudFront console. 但是,这不是您在安全凭据页面上找到的AWS账户的规范用户ID。而是在CloudFront控制台的“Origin Access Identity”链接中找到它。

Here is how to do it .... 这是怎么做的....

First create/obtain the CloudFront Origin Access Identity like this:- 首先创建/获取CloudFront Origin Access Identity,如下所示: -

$oai_id = $cdn->list_oais()->body->CloudFrontOriginAccessIdentitySummary->Id;
if(!$oai_id)
{
    $cdn->create_oai('SOME_IDENTIFIER');
    $oai_id = $cdn->list_oais()->body->CloudFrontOriginAccessIdentitySummary->Id;
}

Now apply the policy to the bucket to allow CloudFront access:- 现在将策略应用于存储桶以允许CloudFront访问: -

$cuid = $cdn->get_oai($oai_id)->body->S3CanonicalUserId;
$policy = new CFPolicy($s3, array(
    'Statement' => array(
        array( // Statement #1
            'Sid' => 'AddPerm',
            'Effect' => 'Allow',
            'Principal' => array(
                'CanonicalUser' => "$cuid"
            ),
            'Action' => array('s3:GetObject'),
            'Resource' => array('arn:aws:s3:::'.$bucket.'/*')
        )
    )
));
// Set the bucket policy
$response = $s3->set_bucket_policy($bucket, $policy);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM