PHP를 사용한 URL 서명 생성 - Amazon CloudFront

PHP를 사용한 URL 서명 생성

PHP를 실행하는 모든 웹 서버는 이 PHP 예제 코드를 사용하여 프라이빗 CloudFront 배포에 대한 정책 설명 및 서명을 만듭니다. 예제 전체에서는 CloudFront 스트리밍을 사용하여 비디오 스트림을 재생하는 서명된 URL 링크가 있는 정상 웹 페이지를 만듭니다. https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/samples/demo-php.zip에서 예제 전체를 다운로드할 수 있습니다.

AWS SDK for PHP에서 UrlSigner 클래스를 사용하여 서명된 URL을 생성할 수도 있습니다. 자세한 내용은 AWS SDK for PHP API 참조Class UrlSigner를 참조하세요.

참고

URL 서명 생성은 서명된 URL을 통해 프라이빗 콘텐츠를 제공하는 프로세스의 한 부분에 불과합니다. 전체 프로세스에 대한 자세한 내용은 서명된 URL 사용을 참조합니다.

예: 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); }

예: 미리 준비된 정책 생성

다음 예제 코드는 서명에 대한 미리 준비된 정책 설명을 구성합니다. 미리 준비된 정책에 대한 자세한 내용은 미리 준비된 정책을 사용하여 서명된 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 . '}}}]}'; // sign the canned policy $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 to work around a flash player bug return encode_query_params($stream_name); }

예: 사용자 지정 정책 생성

다음 예제 코드는 서명에 대한 사용자 지정 정책 설명을 구성합니다. 사용자 지정 정책에 대한 내용은 사용자 지정 정책을 사용하여 서명된 URL 생성을 참조하십시오.

function get_custom_policy_stream_name($video_path, $private_key_filename, $key_pair_id, $policy) { // sign the policy $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 to work around a flash player bug return encode_query_params($stream_name); }

전체 코드 예제

다음 예제 코드는 PHP로 CloudFront 서명 URL을 만드는 전체 예제를 제공합니다. https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/samples/demo-php.zip에서 이 전체 예제를 다운로드할 수 있습니다.

다음 예제에서는 IPv4 및 IPv6 주소 범위를 모두 허용하도록 $policy Condition 요소를 수정할 수 있습니다. 예제는 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 .= $path . $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 .= $path . $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 encode_query_params($stream_name) { // Adobe Flash Player has trouble with query parameters being passed into it, // so replace the bad characters with their URL-encoded forms return str_replace( array('?', '=', '&'), array('%3F', '%3D', '%26'), $stream_name); } 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 to support Flash Player return encode_query_params($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 to support Flash Player return encode_query_params($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'; $video_path = '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); $client_ip = $_SERVER['REMOTE_ADDR']; $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> <script type='text/javascript' src='https://example.cloudfront.net/player/swfobject.js'></script> </head> <body> <h1>Amazon CloudFront</h1> <h2>Canned Policy</h2> <h3>Expires at <?= gmdate('Y-m-d H:i:s T', $expires) ?></h3> <br /> <div id='canned'>The canned policy video will be here</div> <h2>Custom Policy</h2> <h3>Expires at <?= gmdate('Y-m-d H:i:s T', $expires) ?> only viewable by IP <?= $client_ip ?></h3> <div id='custom'>The custom policy video will be here</div> <!-- ************** Have to update the player.swf path to a real JWPlayer instance. The fake one means that external people cannot watch the video right now --> <script type='text/javascript'> var so_canned = new SWFObject('https://files.example.com/player.swf','mpl','640','360','9'); so_canned.addParam('allowfullscreen','true'); so_canned.addParam('allowscriptaccess','always'); so_canned.addParam('wmode','opaque'); so_canned.addVariable('file','<?= $canned_policy_stream_name ?>'); so_canned.addVariable('streamer','rtmp://example.cloudfront.net/cfx/st'); so_canned.write('canned'); var so_custom = new SWFObject('https://files.example.com/player.swf','mpl','640','360','9'); so_custom.addParam('allowfullscreen','true'); so_custom.addParam('allowscriptaccess','always'); so_custom.addParam('wmode','opaque'); so_custom.addVariable('file','<?= $custom_policy_stream_name ?>'); so_custom.addVariable('streamer','rtmp://example.cloudfront.net/cfx/st'); so_custom.write('custom'); </script> </body> </html>

추가 참고: