Crear una firma de URL con PHP - Amazon CloudFront

Crear una firma de URL con PHP

Cualquier servidor web que ejecute PHP puede utilizar este código de ejemplo de PHP para crear instrucciones de política y firmas para distribuciones de CloudFront privadas. El ejemplo completo crea una página web que funciona con enlaces de URL firmadas que reproducen una secuencia de vídeo mediante streaming de CloudFront. Puede descargar el ejemplo completo en https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/samples/demo-php.zip.

También puede crear URL firmadas mediante la clase UrlSigner en AWS SDK for PHP. Para obtener más información, consulte Class UrlSigner en la Referencia de la API de AWS SDK for PHP.

nota

Crear una firma de URL es solo una parte del proceso de entrega de contenido privado mediante una URL firmada. Para obtener más información acerca de todo el proceso, consulte Uso de URL firmadas.

Ejemplo: firma RSA SHA-1

En el siguiente código de ejemplo, la función rsa_sha1_sign aplica el algoritmo hash y firma la instrucción de política. Los argumentos requeridos son una instrucción de política y la clave privada que corresponde a una clave pública que está en un grupo de claves de confianza para la distribución. A continuación, la función url_safe_base64_encode crea una versión de la firma de URL segura.

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

Ejemplo: creación de una política predefinida

El siguiente código de ejemplo crea una instrucción de política predefinida para la firma. Para obtener más información acerca de políticas predefinidas, consulte Creación de una URL firmada mediante una política predefinida.

nota

La variable $expires es una marca temporal fecha/hora que debe ser un número entero, no una cadena.

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

Ejemplo: creación de una política personalizada

El siguiente código de ejemplo crea una instrucción de política personalizada para la firma. Para obtener más información acerca de políticas personalizadas, consulte Creación de una URL firmada mediante una política personalizada.

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

Ejemplo de código completo

El siguiente código de muestra proporciona una demostración completa de la creación de URL firmadas de CloudFront con PHP. Puede descargar este ejemplo completo en https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/samples/demo-php.zip.

En el siguiente ejemplo, puede modificar el elemento $policy de Condition para permitir los rangos de direcciones IPv4 () e IPv6. Para ver un ejemplo, consulte Uso de direcciones IPv6 en políticas de IAM en la Guía del usuario de Amazon Simple Storage Service.

<?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>

Véase también: