View a markdown version of this page

使用 PHP 建立已簽署 Cookie - Amazon CloudFront

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

使用 PHP 建立已簽署 Cookie

下列程式碼範例類似於 使用 PHP 建立 URL 簽章 中建立影片連結的範例。不過,此範例不會在程式碼中簽署 URL,而是使用 create_signed_cookies() 函數簽署 Cookie。用戶端播放器使用 Cookie 對 CloudFront 分佈的每個請求進行身分驗證。

此方法有助於串流內容,例如 HTTP Live Streaming (HLS) 或透過 HTTP 的動態自適應串流 (DASH),其中用戶端需要提出多個請求來擷取資訊清單、區段和相關播放資產。透過使用簽署的 Cookie,用戶端可以驗證每個請求,而不需要為每個區段產生新的已簽署 URL。

注意
  • 建立 URL 簽章只是私有內容提供服務的程序的一部分,以使用已簽署 Cookie。如需詳細資訊,請參閱使用已簽署 Cookie

下列各節將程式碼範例細分為個別部分。您可以在下面找到完整的程式碼範例

建立 RSA SHA-1 或 SHA-256 簽章

此程式碼會執行下列操作:

  1. 函數會使用 SHA-1 雜rsa_sha1_sign湊並簽署政策陳述式。若要改用 SHA-256,請使用如下所示的 rsa_sha256_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); }

    下列函數使用 SHA-256 而非 SHA-1:

    function rsa_sha256_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_ALGO_SHA256); openssl_free_key($pkeyid); return $signature; }

    rsa_sha256_sign 函數與 相同rsa_sha1_sign,但會傳遞OPENSSL_ALGO_SHA256openssl_sign。當您使用 SHA-256 時,請包含值為 的 CloudFront-Hash-Algorithm CookieSHA256

下列程式碼會使用下列 Cookie 屬性來建構 建立簽章的 Cookie:CloudFront-ExpiresCloudFront-SignatureCloudFront-Key-Pair-IdCloudFront-Hash-Algorithm。程式碼使用自訂政策。

function create_signed_cookies($resource, $private_key_filename, $key_pair_id, $expires, $client_ip = null, $hash_algorithm = 'SHA1') { $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); if ($hash_algorithm === 'SHA256') { $signature = rsa_sha256_sign($policy, $private_key_filename); } else { $signature = rsa_sha1_sign($policy, $private_key_filename); } $encoded_signature = url_safe_base64_encode($signature); $cookies = array( 'CloudFront-Policy' => $encoded_policy, 'CloudFront-Signature' => $encoded_signature, 'CloudFront-Key-Pair-Id' => $key_pair_id ); if ($hash_algorithm === 'SHA256') { $cookies['CloudFront-Hash-Algorithm'] = 'SHA256'; } return $cookies; }

如需詳細資訊,請參閱使用自訂政策設定已簽署 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 rsa_sha256_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_ALGO_SHA256); openssl_free_key($pkeyid); return $signature; } function create_signed_cookies($resource, $private_key_filename, $key_pair_id, $expires, $client_ip = null, $hash_algorithm = 'SHA1') { $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); if ($hash_algorithm === 'SHA256') { $signature = rsa_sha256_sign($policy, $private_key_filename); } else { $signature = rsa_sha1_sign($policy, $private_key_filename); } $encoded_signature = url_safe_base64_encode($signature); $cookies = array( 'CloudFront-Policy' => $encoded_policy, 'CloudFront-Signature' => $encoded_signature, 'CloudFront-Key-Pair-Id' => $key_pair_id ); if ($hash_algorithm === 'SHA256') { $cookies['CloudFront-Hash-Algorithm'] = 'SHA256'; } return $cookies; } $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, 'SHA256'); // 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>

您可以使用已簽署 URL,而不是使用已簽署 Cookie。如需詳細資訊,請參閱使用 PHP 建立 URL 簽章