Créer une signature d’URL avec PHP - Amazon CloudFront

Créer une signature d’URL avec PHP

Tout serveur web qui exécute PHP peut utiliser cet exemple de code PHP pour créer des déclarations de politique et des signatures pour les distributions CloudFront privées. L’exemple complet crée une page web avec des liens d’URL signée qui lisent un flux vidéo avec le streaming CloudFront. Vous pouvez télécharger l’exemple complet depuis le fichier demo-php.zip.

Remarques
  • La création d’une signature d’URL n’est qu’une partie du processus d’offre d’un contenu privé avec une URL signée. Pour plus d’informations sur la totalité du processus, consultez Utilisation des URL signées.

  • Vous pouvez aussi créer des URL signées à l’aide de la classe UrlSigner du AWS SDK pour PHP. Pour plus d’informations, consultez Class UrlSigner dans la Référence des API du kit AWS SDK pour PHP.

Les sections suivantes décomposent l’exemple de code en plusieurs parties. Vous trouverez le Exemple de code complet ci-dessous.

Création de la signature RSA SHA-1

Cet exemple de code effectue les opérations suivantes :

  • La fonction rsa_sha1_sign hache et signe la déclaration de politique. Les arguments requis sont une déclaration de politique et la clé privée qui correspond à une clé publique qui se trouve dans un groupe de clés approuvé pour votre distribution.

  • Ensuite, la fonction url_safe_base64_encode crée une version à URL sécurisée de la signature.

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

L’extrait de code suivant utilise les fonctions get_canned_policy_stream_name() et get_custom_policy_stream_name() pour créer une politique prédéfinie et personnalisée. CloudFront utilise les politiques pour créer l’URL de diffusion de la vidéo, notamment pour définir l’heure d’expiration.

Vous pouvez ensuite utiliser une politique prédéfinie ou personnalisée pour définir la gestion de l’accès à votre contenu. Pour savoir quelle option privilégier, consultez la section Choix entre des politiques prédéfinies et personnalisées pour les URL signées.

Création d’une politique prédéfinie

L’exemple de code suivant construit une déclaration de politique prédéfinie pour la signature.

Note

La variable $expires est un horodatage qui doit être un entier et non une chaîne.

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 return $stream_name; }

Pour plus d’informations sur les politiques prédéfinies, consultez Création d’une URL signée à l’aide d’une politique prédéfinie.

Créer une stratégie personnalisée

L’exemple de code suivant construit une déclaration de politique personnalisée pour la signature.

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 return $stream_name; }

Pour plus d’informations sur les politiques personnalisées, consultez Création d’une URL signée utilisant une politique personnalisée.

Exemple de code complet

L’exemple de code suivant fournit une démonstration complète de la création d’URL signées CloudFront avec PHP. Vous pouvez télécharger l’exemple complet depuis le fichier demo-php.zip.

Dans l’exemple suivant, vous pouvez modifier l’élément $policy Condition pour autoriser à la fois des plages d’adresses IPv4 et IPv6. Consultez par exemple Utilisation d’adresses IPv6 dans les politiques IAM dans le Guide de l’utilisateur 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 .= $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 .= $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 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 return $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 return $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'; // Make sure you have "Restrict viewer access" enabled on this path behaviour and using the above Trusted key groups (recommended). $video_path = 'https://example.com/secure/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); // 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']; $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> </head> <body> <h1>Amazon CloudFront</h1> <h2>Canned Policy</h2> <h3>Expires at <?php echo gmdate('Y-m-d H:i:s T', $expires); ?></h3> <br /> <div id='canned'>The canned policy video will be here: <br> <video width="640" height="360" autoplay muted controls> <source src="<?php echo $canned_policy_stream_name; ?>" type="video/mp4"> Your browser does not support the video tag. </video> </div> <h2>Custom Policy</h2> <h3>Expires at <?php echo gmdate('Y-m-d H:i:s T', $expires); ?> only viewable by IP <?php echo $client_ip; ?></h3> <div id='custom'>The custom policy video will be here: <br> <video width="640" height="360" autoplay muted controls> <source src="<?php echo $custom_policy_stream_name; ?>" type="video/mp4"> Your browser does not support the video tag. </video> </div> </body> </html>

Pour obtenir plus exemples sur la signature d’URL, consultez les rubriques suivantes :

Au lieu d’utiliser des URL signées pour créer la signature, vous pouvez utiliser des cookies signés. Pour plus d’informations, consultez Création de cookies signés avec PHP.