PHP を使用して署名付き cookie を作成する - Amazon CloudFront

PHP を使用して署名付き cookie を作成する

次のコード例は、動画へのリンクを作成するという点で PHP を使用して URL 署名を作成する の例に似ています。ただし、コード内の URL に署名する代わりに、この例では create_signed_cookies() 関数を使用して cookie に署名します。クライアント側のプレイヤーは、cookie を使用して CloudFront ディストリビューションへの各リクエストを認証します。

このアプローチは、HTTP ライブストリーミング (HLS) や HTTP 経由の動的アダプティブストリーミング (DASH) などのコンテンツをストリーミングする場合に便利です。この場合、クライアントはマニフェスト、セグメント、および関連する再生アセットを取得するために複数のリクエストを行う必要があります。署名付き cookie を使用することで、クライアントはセグメントごとに新しい署名付き URL を生成することなく、各リクエストを認証できます。

注記
  • URL 署名の作成は、署名付き cookie を使用してプライベートコンテンツを提供するプロセスの一環にすぎません。詳細については、「署名付き Cookie を使用する」を参照してください。

以下のセクションでは、コード例を個別のパートに分解します。完全なコードサンプルは以下にあります。

RSA SHA-1 署名を作成する

このコード例では、次の操作を行います。

  1. 関数 rsa_sha1_sign は、ポリシーステートメントをハッシュ化して署名します。必要な引数は、ポリシーステートメントと、ディストリビューションの信頼されたキーグループにあるパブリックキーに対応するプライベートキーです。

  2. 次に、url_safe_base64_encode 関数で、URL で使用可能なバージョンの署名を作成します。

    function rsa_sha1_sign($policy, $private_key_filename) { $signature = ""; $fp = fopen($private_key_filename, "r"); $priv_key = fread($fp, 8192); fclose($fp); $pkeyid = openssl_get_privatekey($priv_key); openssl_sign($policy, $signature, $pkeyid); openssl_free_key($pkeyid); return $signature; } function url_safe_base64_encode($value) { $encoded = base64_encode($value); return str_replace( array('+', '=', '/'), array('-', '_', '~'), $encoded); }

次のコードコンストラクトは、cookie 属性として CloudFront-ExpiresCloudFront-SignatureCloudFront-Key-Pair-Id を使用して署名付き cookie を作成します。このコードでは、カスタムポリシーを使用します。

function create_signed_cookies($resource, $private_key_filename, $key_pair_id, $expires, $client_ip = null) { $policy = array( 'Statement' => array( array( 'Resource' => $resource, 'Condition' => array( 'DateLessThan' => array('AWS:EpochTime' => $expires) ) ) ) ); if ($client_ip) { $policy['Statement'][0]['Condition']['IpAddress'] = array('AWS:SourceIp' => $client_ip . '/32'); } $policy = json_encode($policy); $encoded_policy = url_safe_base64_encode($policy); $signature = rsa_sha1_sign($policy, $private_key_filename); $encoded_signature = url_safe_base64_encode($signature); return array( 'CloudFront-Policy' => $encoded_policy, 'CloudFront-Signature' => $encoded_signature, 'CloudFront-Key-Pair-Id' => $key_pair_id ); }

詳細については、「カスタムポリシーを使用して署名付き Cookie を設定する」を参照してください。

完全なコード

次のコードサンプルでは、PHP で CloudFront 署名付き cookie を作成する詳細な方法を示します。完全な例については、demo-php.zip ファイルからダウンロードできます。

次の例では、$policy Condition エレメントを変更して、IPv4 アドレス範囲と IPv6 アドレス範囲の両方を許可できます。例については、「Amazon Simple Storage Service ユーザーガイド」の「IAM ポリシーでの IPv6 アドレスの使用」を参照してください。

<?php function rsa_sha1_sign($policy, $private_key_filename) { $signature = ""; $fp = fopen($private_key_filename, "r"); $priv_key = fread($fp, 8192); fclose($fp); $pkeyid = openssl_get_privatekey($priv_key); openssl_sign($policy, $signature, $pkeyid); openssl_free_key($pkeyid); return $signature; } function url_safe_base64_encode($value) { $encoded = base64_encode($value); return str_replace( array('+', '=', '/'), array('-', '_', '~'), $encoded); } function create_signed_cookies($resource, $private_key_filename, $key_pair_id, $expires, $client_ip = null) { $policy = array( 'Statement' => array( array( 'Resource' => $resource, 'Condition' => array( 'DateLessThan' => array('AWS:EpochTime' => $expires) ) ) ) ); if ($client_ip) { $policy['Statement'][0]['Condition']['IpAddress'] = array('AWS:SourceIp' => $client_ip . '/32'); } $policy = json_encode($policy); $encoded_policy = url_safe_base64_encode($policy); $signature = rsa_sha1_sign($policy, $private_key_filename); $encoded_signature = url_safe_base64_encode($signature); return array( 'CloudFront-Policy' => $encoded_policy, 'CloudFront-Signature' => $encoded_signature, 'CloudFront-Key-Pair-Id' => $key_pair_id ); } $private_key_filename = '/home/test/secure/example-priv-key.pem'; $key_pair_id = 'K2JCJMDEHXQW5F'; $base_url = 'https://d1234.cloudfront.net'; $expires = time() + 3600; // 1 hour from now // 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']; // For HLS manifest and segments (using wildcard) $hls_resource = $base_url . '/sign/*'; $signed_cookies = create_signed_cookies($hls_resource, $private_key_filename, $key_pair_id, $expires, $client_ip); // Set the cookies $cookie_domain = parse_url($base_url, PHP_URL_HOST); foreach ($signed_cookies as $name => $value) { setcookie($name, $value, $expires, '/', $cookie_domain, true, true); } ?> <!DOCTYPE html> <html> <head> <title>CloudFront Signed HLS Stream with Cookies</title> </head> <body> <h1>Amazon CloudFront Signed HLS Stream with Cookies</h1> <h2>Expires at <?php echo gmdate('Y-m-d H:i:s T', $expires); ?> only viewable by IP <?php echo $client_ip; ?></h2> <div id='hls-video'> <video id="video" width="640" height="360" controls></video> </div> <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script> <script> var video = document.getElementById('video'); var manifestUrl = '<?php echo $base_url; ?>/sign/manifest.m3u8'; if (Hls.isSupported()) { var hls = new Hls(); hls.loadSource(manifestUrl); hls.attachMedia(video); } else if (video.canPlayType('application/vnd.apple.mpegurl')) { video.src = manifestUrl; } </script> </body> </html>

署名付き cookie を使用する代わりに、署名付き URL を使用できます。詳細については、「PHP を使用して URL 署名を作成する」を参照してください。