AWS Amazon Cloudfront PHP的签名url

AWS Amazon Cloudfront PHP的签名url,php,amazon-web-services,amazon-s3,amazon-cloudfront,Php,Amazon Web Services,Amazon S3,Amazon Cloudfront,我正试图在支持Cloudfront的Amazon S3存储桶上提供指向私人内容的有时间限制的链接 我希望能够使用AWS PHP API $credentials = array("key" => $variables->strAmazonAccessKey, "secret" => $variables->strAmazonSecretKey); $s3 = new AmazonS3($credentials); $cdn = new AmazonCloudFront($

我正试图在支持Cloudfront的Amazon S3存储桶上提供指向私人内容的有时间限制的链接

我希望能够使用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'));
但我一直收到拒绝访问的消息

<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>BD2B4CE946ED67C4</RequestId>
<HostId>
JrBu9+HqhGwzRA4ILFeT2SGyp5nXEY/RrYWQDz2dzdWDIRTgVy2i3Llm460ok99M
</HostId>
</Error>
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-----
我可能在那里做错了什么,但我希望得到的是关于密钥或签名的错误,而不是拒绝访问的消息

我还尝试使用以下方法手动签名,但得到相同的错误,只是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); 

我终于解决了这个问题

亚马逊似乎对此并不十分清楚。。。隐藏在AWS文档的深处,您被指示在S3 bucket上设置bucket权限,以允许CloudFront访问它

当您必须在策略上设置Principal属性时,会导致进一步的混淆,因为这表明您需要获取规范用户ID。但是,这不是在安全凭据页面上找到的AWS帐户的规范用户ID。。而是在CloudFront控制台上的“源站访问标识”链接中找到

下面是如何做到这一点

首先创建/获取CloudFront源站访问标识,如下所示:-

$oai_id = $cdn->list_oais()->body->CloudFrontOriginAccessIdentitySummary->Id;
if(!$oai_id)
{
    $cdn->create_oai('SOME_IDENTIFIER');
    $oai_id = $cdn->list_oais()->body->CloudFrontOriginAccessIdentitySummary->Id;
}
现在将该策略应用于bucket以允许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);

这是很明显的,但我真的希望你不是真的在使用这里发布的私钥。