2

このサンプルに従って、PHP http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CreateURL_PHP.htmlを使用して CloudFront で署名付き URL を作成しています。

そして、すべて正常に動作し、RTMP ディストリビューションと HTTP ディストリビューションの両方の署名付き URL を生成しています。

ただし、署名 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 個の署名付き URL を作成するのにかかる時間を確認することにしました。

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;
    }

その while ループで 500 個の署名付き URL を生成するのに、ローカル マシンで約 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 関数はスクリプトを大幅に遅くします。これらの署名付き URL を生成していて、かなりの処理能力を必要とするため、これは正常なことでしょうか?

私はいくつかの試行を行いました.ここでは、それぞれ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

また、ディストリビューション内のどのファイルでも機能する署名を作成する方法を知りたいです。そのフォルダーまたはディストリビューションの下にあるすべてのファイルに使用できる署名を生成できるワイルドカード。それが可能であるとどこかで読みましたが、上記のサンプルをどのように使用するかはわかりません。おそらく、リクエストで返される各ファイルではなく、リクエストごとに単一の署名を作成できれば、それほど集中的ではないでしょう.

ありがとう!

4

2 に答える 2

0

「fopen()」を削除して、秘密鍵にハードコードされた値を使用してみましたか?

例:

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() はファイル システムにアクセスする必要があると思います。一般に、これは物事を遅くします。

于 2014-06-04T23:07:27.400 に答える
0

rsaモジュールを使用して署名を計算するBoto (AWS の Python SDK) でも同じパフォーマンスの問題が発生します。問題は、このコンテキストでは RSA 計算が遅いという事実に単純に帰着すると思います。解決策は、プライベート コンテンツを処理するための設定またはワークフローを調整することにあると思います/願っています。

于 2015-07-13T06:00:00.620 に答える