PHP を使用して URL 署名を作成する
PHP を実行するすべてのウェブサーバーでは、この PHP サンプルコードを使用して、CloudFront のプライベートディストリビューション用のポリシーステートメントと署名を作成できます。この完全なサンプルでは、CloudFront ストリーミングを使用してビデオストリームを再生する署名付き URL リンクが含まれた、実際に動作するウェブページを作成します。完全な例については、demo-php.zip ファイルからダウンロードできます。
メモ
-
URL 署名の作成は、署名付き URL を使用してプライベートコンテンツを供給するためのプロセスの 1 パートにすぎません。プロセス全体の詳細については、「署名付き URL を使用する」を参照してください。
-
AWS SDK for PHP の
UrlSigner
クラスを使用して署名付き URL を作成することもできます。詳細については、AWS SDK for PHP API リファレンスの「Class UrlSigner」を参照してください。
以下のセクションでは、コード例を個別のパートに分解します。「完全なサンプルコード」は以下にあります。
RSA SHA-1 署名を作成する
このコード例では、次の操作を行います。
-
関数
rsa_sha1_sign
は、ポリシーステートメントをハッシュ化して署名します。必要な引数は、ポリシーステートメントと、ディストリビューションの信頼されたキーグループにあるパブリックキーに対応するプライベートキーです。 -
次に、
url_safe_base64_encode
関数で、URL で使用可能なバージョンの署名を作成します。
function rsa_sha1_sign($policy, $private_key_filename) { $signature = ""; // load the private key $fp = fopen($private_key_filename, "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; } 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); }
次のコードスニペットでは、get_canned_policy_stream_name()
関数と get_custom_policy_stream_name()
関数を使用して既定ポリシーとカスタムポリシーを作成します。CloudFront は、これらのポリシーを使用して、有効期限を指定するとともに、動画をストリーミングするための URL を作成します。
次に、既定ポリシーまたはカスタムポリシーを使用して、コンテンツへのアクセスを管理する方法を決定できます。どちらを選択するかの詳細については、「署名付き URL に既定ポリシーとカスタムポリシーのどちらを使用するかを決定する」セクションを参照してください。
既定ポリシーを作成する
以下のサンプルコードでは、署名用の既定ポリシーステートメントを作成します。
注記
$expires
変数は、文字列ではなく整数である必要がある日時スタンプです。
function get_canned_policy_stream_name($video_path, $private_key_filename, $key_pair_id, $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 . '}}}]}'; // the policy contains characters that cannot be part of a URL, so we base64 encode it $encoded_policy = url_safe_base64_encode($canned_policy); // sign the original policy, not the encoded version $signature = rsa_sha1_sign($canned_policy, $private_key_filename); // make the signature safe to be included in a URL $encoded_signature = url_safe_base64_encode($signature); // combine the above into a stream name $stream_name = create_stream_name($video_path, null, $encoded_signature, $key_pair_id, $expires); // URL-encode the query string characters return $stream_name; }
既定ポリシーの詳細については、「既定ポリシーを使用して署名付き URL を作成する」を参照してください。
カスタムポリシーの作成
以下のサンプルコードでは、署名用のカスタムポリシーステートメントを作成します。
function get_custom_policy_stream_name($video_path, $private_key_filename, $key_pair_id, $policy) { // the policy contains characters that cannot be part of a URL, so we base64 encode it $encoded_policy = url_safe_base64_encode($policy); // sign the original policy, not the encoded version $signature = rsa_sha1_sign($policy, $private_key_filename); // make the signature safe to be included in a URL $encoded_signature = url_safe_base64_encode($signature); // combine the above into a stream name $stream_name = create_stream_name($video_path, $encoded_policy, $encoded_signature, $key_pair_id, null); // URL-encode the query string characters return $stream_name; }
カスタムポリシーの詳細については、「カスタムポリシーを使用して署名付き URL を作成する」を参照してください。
完全なサンプルコード
次のコードサンプルでは、PHP で CloudFront 署名付き URL を作成する詳細な方法を示します。完全な例については、demo-php.zip ファイルからダウンロードできます。
次の例では、$policy
Condition
エレメントを変更して、IPv4 アドレス範囲と IPv6 アドレス範囲の両方を許可できます。例については、「Amazon Simple Storage Service ユーザーガイド」の「IAM ポリシーでの IPv6 アドレスの使用」を参照してください。
<?php function rsa_sha1_sign($policy, $private_key_filename) { $signature = ""; // load the private key $fp = fopen($private_key_filename, "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; } 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); } function create_stream_name($stream, $policy, $signature, $key_pair_id, $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 ? '?' : '&'; // the presence of an expires time means we're using a canned policy if($expires) { $result .= $separator . "Expires=" . $expires . "&Signature=" . $signature . "&Key-Pair-Id=" . $key_pair_id; } // not using a canned policy, include the policy itself in the stream name else { $result .= $separator . "Policy=" . $policy . "&Signature=" . $signature . "&Key-Pair-Id=" . $key_pair_id; } // new lines would break us, so remove them return str_replace('\n', '', $result); } function get_canned_policy_stream_name($video_path, $private_key_filename, $key_pair_id, $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 . '}}}]}'; // the policy contains characters that cannot be part of a URL, so we base64 encode it $encoded_policy = url_safe_base64_encode($canned_policy); // sign the original policy, not the encoded version $signature = rsa_sha1_sign($canned_policy, $private_key_filename); // make the signature safe to be included in a URL $encoded_signature = url_safe_base64_encode($signature); // combine the above into a stream name $stream_name = create_stream_name($video_path, null, $encoded_signature, $key_pair_id, $expires); // URL-encode the query string characters return $stream_name; } function get_custom_policy_stream_name($video_path, $private_key_filename, $key_pair_id, $policy) { // the policy contains characters that cannot be part of a URL, so we base64 encode it $encoded_policy = url_safe_base64_encode($policy); // sign the original policy, not the encoded version $signature = rsa_sha1_sign($policy, $private_key_filename); // make the signature safe to be included in a URL $encoded_signature = url_safe_base64_encode($signature); // combine the above into a stream name $stream_name = create_stream_name($video_path, $encoded_policy, $encoded_signature, $key_pair_id, null); // URL-encode the query string characters return $stream_name; } // Path to your private key. Be very careful that this file is not accessible // from the web! $private_key_filename = '/home/test/secure/example-priv-key.pem'; $key_pair_id = 'K2JCJMDEHXQW5F'; // Make sure you have "Restrict viewer access" enabled on this path behaviour and using the above Trusted key groups (recommended). $video_path = 'https://example.com/secure/example.mp4'; $expires = time() + 300; // 5 min from now $canned_policy_stream_name = get_canned_policy_stream_name($video_path, $private_key_filename, $key_pair_id, $expires); // Get the viewer real IP from the x-forward-for header as $_SERVER['REMOTE_ADDR'] will return viewer facing IP. An alternative option is to use CloudFront-Viewer-Address header. Note that this header is a trusted CloudFront immutable header. Example format: IP:PORT ("CloudFront-Viewer-Address": "1.2.3.4:12345") $client_ip = $_SERVER['HTTP_X_FORWARDED_FOR']; $policy = '{'. '"Statement":['. '{'. '"Resource":"'. $video_path . '",'. '"Condition":{'. '"IpAddress":{"AWS:SourceIp":"' . $client_ip . '/32"},'. '"DateLessThan":{"AWS:EpochTime":' . $expires . '}'. '}'. '}'. ']' . '}'; $custom_policy_stream_name = get_custom_policy_stream_name($video_path, $private_key_filename, $key_pair_id, $policy); ?> <html> <head> <title>CloudFront</title> </head> <body> <h1>Amazon CloudFront</h1> <h2>Canned Policy</h2> <h3>Expires at <?php echo gmdate('Y-m-d H:i:s T', $expires); ?></h3> <br /> <div id='canned'>The canned policy video will be here: <br> <video width="640" height="360" autoplay muted controls> <source src="<?php echo $canned_policy_stream_name; ?>" type="video/mp4"> Your browser does not support the video tag. </video> </div> <h2>Custom Policy</h2> <h3>Expires at <?php echo gmdate('Y-m-d H:i:s T', $expires); ?> only viewable by IP <?php echo $client_ip; ?></h3> <div id='custom'>The custom policy video will be here: <br> <video width="640" height="360" autoplay muted controls> <source src="<?php echo $custom_policy_stream_name; ?>" type="video/mp4"> Your browser does not support the video tag. </video> </div> </body> </html>
その他の URL 署名の例については、以下のトピックを参照してください。
署名 URL を使用して署名を作成する代わりに、署名付き cookie を使用できます。詳細については、「PHP を使用して署名付き cookie を作成する」を参照してください。