我正在关注此示例,以使用PHP在CloudFront上创建签名URL http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CreateURL_PHP.html
我一切正常,并为RTMP发行版和HTTP发行版生成签名URL。
但是我注意到生成Sign URL需要相当长的时间,我想知道在生产中使用数千个请求会产生什么影响。
我做了一些测试,似乎很长时间都是由于php-openssl功能。
以下是代码:
<?php
class Cloudfront {
const KEYPAIRID = 'MYKEYPAIRID';
const PVTKEYFILE = '/home/keys/myprivatekey.pem';
public function rsa_sha1_sign($policy) {
$signature = "";
// load the private key
$fp = fopen(self::PVTKEYFILE, "r");
$priv_key = fread($fp, 8192);
fclose($fp);
$pkeyid = openssl_get_privatekey($priv_key);
// compute signature
openssl_sign($policy, $signature, $pkeyid);
// free the key from memory
openssl_free_key($pkeyid);
return $signature;
}
public function simulated_rsa_sha1_sign($policy) {
// create a simulated signature
$signature = "©3•{š(|i~'{µÜr…6—\L¶…ÙiÃÔh@ç÷S„Aóö¯‡d‰‹{¦ºxòrd)Xcª
Áh‚°Bgþ èòëÿô Š#CßFe ÓÒ>v1 R€¥#–þ*¸çGÀýƒ Ј¾F<t)eV7¿ø_ŒQÎiXXU s˜¦Ij:ý
ÒR ‹ÚQ§ Çm8à ºâ*+äÇjƒãýO 4 ~ Uöeóy˜¢93_0iy §âE– a÷f¥y¿ÈãÏ`‹ _ì`ß ½õ ‹*
ÁM‘çõD jrüB •d˜¥ èp Òü¿Ö NŒ«éoI X €v=RÌlŠ¤ /Á û9Yš¾î";
// load the private key file although is not actually used
$fp = fopen(self::PVTKEYFILE, "r");
$priv_key = fread($fp, 8192);
fclose($fp);
return $signature;
}
public function url_safe_base64_encode($value) {
$encoded = base64_encode($value);
// replace unsafe characters +, = and / with the safe characters -, _ and ~
return str_replace(
array('+', '=', '/'), array('-', '_', '~'), $encoded);
}
public function create_stream_name($stream, $signature, $expires) {
$result = $stream;
// if the stream already contains query parameters, attach the new query parameters to the end
// otherwise, add the query parameters
$separator = strpos($stream, '?') == FALSE ? '?' : '&';
$result .= $separator . "Expires=" . $expires . "&Key-Pair-Id=" . self::KEYPAIRID . "&Signature=" . $signature;
// new lines would break us, so remove them
return str_replace('\n', '', $result);
}
public function get_signed_stream_name($video_path, $expires) {
// this policy is well known by CloudFront, but you still need to sign it, since it contains your parameters
$canned_policy = '{"Statement":[{"Resource":"' . $video_path . '","Condition":{"DateLessThan":{"AWS:EpochTime":' . $expires . '}}}]}';
// sign the original policy, not the encoded version
$signature = $this->rsa_sha1_sign($canned_policy);
// make the signature safe to be included in a url
$encoded_signature = $this->url_safe_base64_encode($signature);
// combine the above into a stream name
$stream_name = $this->create_stream_name($video_path, $encoded_signature, $expires);
return $stream_name;
}
}
这与CloudFront在其文档上的示例基本相同。然后我创建了一个控制器,我调用get_signed_stream_name()来生成签名的URL。我决定做一个while循环,看看创建500个签名网址需要多长时间。
public function signedurl() {
// Script start
$start = microtime(true);
$this->load->helper('cloudfront');
$this->cloudfront = new Cloudfront();
$i = 1;
while ($i <= 500) {
$expires = time() + rand(300, 900);
$http_video_path = 'http://mydistribution.cloudfront.net/myvideo.mp4';
$signed_http_url = $this->cloudfront->get_signed_stream_name($http_video_path, $expires);
echo '<strong>HTTP Signed URL:</strong> <br />' . $signed_http_url;
echo '<br /><br />';
$i++;
}
// Script end
$time_taken = microtime(true) - $start;
echo $time_taken;
}
生成500个已签名的URL,而while循环在我的本地计算机上花了大约11秒。然后我决定改变之类的:
$signature = $this->rsa_sha1_sign($canned_policy);
到
$signature = $this->simulated_rsa_sha1_sign($canned_policy);
如果一切都在运行,除了调用php-openssl函数openssl_get_privatekey(),openssl_sign(),openssl_free_key()之外,看看发生了什么。
我使用500 while循环运行相同的脚本,花了0.090秒。所以基本上php-openssl函数使脚本慢了很多。这是我应该担心的事情,这是正常的,因为我正在生成这些签名的网址,它需要相当大的处理能力?
我做了几次尝试,以下是每次尝试3次的样本时间。
Real code using OpenSSL functions generating 500 signed url calls:
11.135037899
11.6025328636
11.0253090858
500 URLs simulated without using the OpenSSL functions:
0.0828909873962
0.0903220176697
0.0916609764099
此外,我想知道如何创建适用于发行版中任何文件的签名。一个通配符,我可以生成一个签名,可以用于该文件夹或分发下的所有文件。我在某处读到有可能,但不确定如何使用上面的这些样本。也许如果我可以为每个请求创建一个签名,而不是为请求中返回的每个文件创建一个签名,那就不那么强了。
谢谢!
答案 0 :(得分:0)
您是否尝试过删除&#34; fopen()&#34;并使用私钥的硬编码值?
示例:
function getPrivateKey() {
$privateKey = '-----BEGIN RSA PRIVATE KEY-----
abc
-----END RSA PRIVATE KEY-----';
return str_replace("\t", '', $privateKey);
}
如果您仍需要将密钥插入外部文件,请尝试使用php include()并利用APC缓存。
用于处理批量私钥;您可以使用Iterator或scan_dir,根据正则表达式扫描文件,包含文件并将其内容分配到SSL密钥数组中。再次,您将利用APC。不幸的是,我认为scandir()需要访问你的文件系统。通常这会减慢事情。
答案 1 :(得分:0)
我观察到与使用rsa
模块计算签名的Boto(AWS的Python SDK)相同的性能问题。我认为问题只是归结为RSA计算在这种情况下很慢的事实。我认为/希望解决方案在于调整处理私有内容的设置或工作流程。