使用 PHP 创建签名 Cookie
以下代码示例与使用 PHP 创建 URL 签名中的示例类似,创建指向视频的链接。但是,此示例没有对代码中的 URL 进行签名,而是使用 create_signed_cookies()
功能对 Cookie 进行签名。客户端播放器使用 Cookie 对向 CloudFront 分配发出的每个请求进行身份验证。
这种方法对于流式传输内容非常有用,例如 HTTP 直播(HLS,HTTP Live Streaming)或基于 HTTP 的动态自适应流式传输(DASH,Dynamic adaptive streaming over HTTP),在这种情况下,客户端需要发出多个请求来检索清单、片段和相关的播放资产。通过使用签名 Cookie,客户端可以对每个请求进行身份验证,而无需为每个分段生成新的签名 URL。
注意
-
在使用签名 URL 提供私有内容的过程中,创建 URL 签名只是其中的一部分。有关更多信息,请参阅 使用签名 Cookie。
以下部分将代码示例细分到各个单独的部分。您可以在下面找到完整的代码示例。
创建 RSA SHA-1 签名
本代码示例执行以下操作:
-
函数
rsa_sha1_sign
执行哈希操作并签署策略声明。所需的参数是策略语句和私有密钥,该私有密钥对应于分配的可信密钥组中的公有密钥。 -
接下来,
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
下面的代码构造了创建签名 Cookie 的过程,使用的 Cookie 属性包括:CloudFront-Expires
、CloudFront-Signature
和 CloudFront-Key-Pair-Id
。代码使用自定义策略。
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 签名。