Amazon CloudFront 上 Protected Content 的 URL Sign...

Amazon CloudFront 也可以設定要簽名才能抓檔案,只是 URL Sign 設計的觀念跟 Amazon S3 完全不一樣,這不一致的調調很... 詭異...

大致上有這些差異:

  • Amazon S3 用的是 HMAC-SHA1 的機制簽名 (shared secret,也就是 Amazon S3 與你都有同一把 key),而 Amazon CloudFront 則是用 RSA key 簽名 (public key,也就是 Amazon CloudFront 存放 public key,你自己存放 private key)。
  • 也因為是使用 RSA key,有人會誤解跟 Amazon EC2 用的 RSA key 相同。但實際上需要在 Security Credentials 頁裡設,有專門對 Amazon CloudFront 用的 RSA key 的段落。
  • 自己對 Base64 編碼再處理,避開使用 += 以及 /。但不是有標準可以用嗎,為什麼要自己發明呢...
  • 引入 Policy 的彈性機制,不僅可以對時間控制,也可以對 IP address 控制,但 Policy 這是帶在 URL 裡傳進去的... 你可以看到我的程式碼內產生出 $json_str 後簽完名帶到 URL 內了。

官方的 CloudFront Signed URLs in PHP 這篇的範例程式碼其實很清楚了,要直接拿去用其實也沒麼問題。我自己整理後是這樣:

<?php

$key_pair_id = 'APKA...';
$pem_file = '';
$resource = 'http://test2-cdn.gslin.org/test.txt';

$expires = time() + 3600;

$json_str = json_encode(
    array(
        'Statement' => array(
            array(
                'Resource' => $resource,
                'Condition' => array(
                    'DateLessThan' => array(
                        'AWS:EpochTime' => $expires
                    )
                )
            )
        )
    ),
    JSON_UNESCAPED_SLASHES
);

$buf = file_get_contents($pem_file);
$key = openssl_get_privatekey($buf);

openssl_sign($json_str, $signed_policy, $key, OPENSSL_ALGO_SHA1);

openssl_free_key($key);

$signature = str_replace(
    array('+', '=', '/'),
    array('-', '_', '~'),
    base64_encode($signed_policy)
);

echo "${resource}?",
    "Expires=${expires}&",
    "Signature=${signature}&",
    "Key-Pair-Id=${key_pair_id}\n";

反正你搞不太懂 Amazon 為什麼要這樣設計的... =_=

This entry was posted in AWS, CDN, Cloud, Computer, Murmuring, Network, Programming, WWW and tagged , , , , , , , , , , , , . Bookmark the permalink.

4 Responses to Amazon CloudFront 上 Protected Content 的 URL Sign...

  1. Dennis Cheung says:

    base64 in URL 避開使用 +、= 以及 / 基本上是 de-factro standard

  2. Gea-Suan Lin says:

    用在 url 要避開,但用在 url 參數裡有 x-www-form-urlencoded 格式可以用 (HTML4/5 standard),各語言都有現成的實做可以套...

    但 CloudFront 這邊等於是要人工 escape hack...

  3. Guest says:

    那不就失了 base64 只用 64 個組合去減少payload size 的原意嗎?? URL 要 escape 單單用 urlencode 就可以. 但要 shorter URL 就是要用 base64-for-url _(http://en.wikipedia.org/wiki/Base64 # URL applications )

    只是奇怪還沒有人把它明確 standardize 給它有名有份的 API/doc

    當年 JSON 也是突然變出來的

  4. Dennis Cheung says:

    那不就失了 base64 只用 64 個組合去減少payload size 的原意嗎?? URL 要 escape 單單用 urlencode 就可以. 但要 shorter URL 就是要用 base64-for-url _(http://en.wikipedia.org/wiki/B... # URL applications )

    只是奇怪還沒有人把它明確 standardize 給它有名有份的 API/doc

    當年 JSON 也是突然變出來的

Leave a Reply

Your email address will not be published. Required fields are marked *