

# PHP を使用して URL 署名を作成する
<a name="CreateURL_PHP"></a>

PHP を実行するすべてのウェブサーバーでは、この PHP サンプルコードを使用して、CloudFront のプライベートディストリビューション用のポリシーステートメントと署名を作成できます。この完全なサンプルでは、CloudFront ストリーミングを使用してビデオストリームを再生する署名付き URL リンクが含まれた、実際に動作するウェブページを作成します。完全な例については、[demo-php.zip](samples/demo-php.zip) ファイルからダウンロードできます。

**注意事項**  
URL 署名の作成は、署名付き URL を使用してプライベートコンテンツを供給するためのプロセスの 1 パートにすぎません。プロセス全体の詳細については、「[署名付き URL を使用する](private-content-signed-urls.md)」を参照してください。
AWS SDK for PHP の `UrlSigner` クラスを使用して署名付き URL を作成することもできます。詳細については、*AWS SDK for PHP API リファレンス*の「[Class UrlSigner](https://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.CloudFront.UrlSigner.html)」を参照してください。

**Topics**
+ [

## RSA SHA-1 署名を作成する
](#sample-rsa-sign)
+ [

## 既定ポリシーを作成する
](#sample-canned-policy)
+ [

## カスタムポリシーを作成するには
](#sample-custom-policy)
+ [

## 完全なサンプルコード
](#full-example)

以下のセクションでは、コード例を個別のパートに分解します。「[完全なサンプルコード](#full-example)」は以下にあります。

## RSA SHA-1 署名を作成する
<a name="sample-rsa-sign"></a>

このコード例では、次の操作を行います。
+ 関数 `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);
}
```

次のコードスニペットでは、`get_canned_policy_stream_name()` 関数と `get_custom_policy_stream_name()` 関数を使用して既定ポリシーとカスタムポリシーを作成します。CloudFront は、これらのポリシーを使用して、有効期限を指定するとともに、動画をストリーミングするための URL を作成します。

次に、既定ポリシーまたはカスタムポリシーを使用して、コンテンツへのアクセスを管理する方法を決定できます。どちらを選択するかの詳細については、「[署名付き URL に既定ポリシーとカスタムポリシーのどちらを使用するかを決定する](private-content-signed-urls.md#private-content-choosing-canned-custom-policy)」セクションを参照してください。

## 既定ポリシーを作成する
<a name="sample-canned-policy"></a>

以下のサンプルコードでは、署名用の*既定*ポリシーステートメントを作成します。

**注記**  
`$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 . '}}}]}';
    // 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;
}
```

既定ポリシーの詳細については、「[既定ポリシーを使用して署名付き URL を作成する](private-content-creating-signed-url-canned-policy.md)」を参照してください。

## カスタムポリシーを作成するには
<a name="sample-custom-policy"></a>

以下のサンプルコードでは、署名用の*カスタム*ポリシーステートメントを作成します。

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

カスタムポリシーの詳細については、「[カスタムポリシーを使用して署名付き URL を作成する](private-content-creating-signed-url-custom-policy.md)」を参照してください。

## 完全なサンプルコード
<a name="full-example"></a>

次のコードサンプルでは、PHP で CloudFront 署名付き URL を作成する詳細な方法を示します。完全な例については、[demo-php.zip](samples/demo-php.zip) ファイルからダウンロードできます。

次の例では、`$policy` `Condition` エレメントを変更して、IPv4 アドレス範囲と IPv6 アドレス範囲の両方を許可できます。例については、「Amazon Simple Storage Service ユーザーガイド」の「[IAM ポリシーでの IPv6 アドレスの使用](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ipv6-access.html#ipv6-access-iam)」を参照してください。**

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

その他の URL 署名の例については、以下のトピックを参照してください。
+ [Perl を使用して URL 署名を作成する](CreateURLPerl.md)
+ [C\$1 と .NET Framework を使用して URL 署名を作成する](CreateSignatureInCSharp.md)
+ [Java を使用して URL 署名を作成する](CFPrivateDistJavaDevelopment.md)

署名 URL を使用して署名を作成する代わりに、署名付き cookie を使用できます。詳細については、「[PHP を使用して署名付き cookie を作成する](signed-cookies-PHP.md)」を参照してください。