How To Use Amazon S3 To Serve Private Membership Site Content

Discussion in 'Membership Sites' started by TechnicalSergio, May 15, 2010.

  1. TechnicalSergio

    TechnicalSergio Newbie

    Joined:
    Jan 19, 2010
    Messages:
    32
    Likes Received:
    80
    Occupation:
    Stackin' Paper
    Location:
    San Jose
    Would you like to use Amazon's S3 servers to take care of your private membership site content?

    I'd been looking for a way to do this and no one could give me a straight answer, so I spent a few hours the other day and have finally got it working.

    I know a lot of you could benefit from this info, so here goes...

    1. Upload your content to S3 -- I use the Firefox plugin "S3 Organizer". The security settings should be private by default.

    2. Create a php file on your web server with the following code. Make sure you replace YOUR-KEY and YOUR-OTHER-KEY with your correct Amazon keys:

    Code:
    <?php
      // grab this with "pear install --onlyreqdeps Crypt_HMAC"
    require_once('Crypt/HMAC.php');
    
    // Amazon S3 credentials
    define('S3_ACCESS_KEY_ID', 'YOUR-KEY');
    define('S3_SECRET_ACCESS_KEY', 'YOUR-OTHER-KEY');
    
    /**
    * Generate a link to download a file from Amazon S3 using query string
    * authentication. This link is only valid for a limited amount of time.
    *
    * @param $bucket The name of the bucket in which the file is stored.
    * @param $filekey The key of the file, excluding the leading slash.
    * @param $expires The amount of time the link is valid (in seconds).
    * @param $operation The type of HTTP operation. Either GET or HEAD.
    */
    
    function mymodule_get_s3_auth_link($bucket, $filekey, $expires = 3000, $operation = 'GET') {
    $expire_time = time() + $expires;
    $filekey = rawurlencode($filekey);
    $filekey = str_replace('%2F', '/', $filekey);
    $path = $bucket .'/'. $filekey;
    
    /**
    * StringToSign = HTTP-VERB + "\n" +
    * Content-MD5 + "\n" +
    * Content-Type + "\n" +
    * Expires + "\n" +
    * CanonicalizedAmzHeaders +
    * CanonicalizedResource;
    */
    
    $stringtosign =
    $operation ."\n". // type of HTTP request (GET/HEAD)
    "\n". // Content-MD5 is meaningless for GET
    "\n". // Content-Type is meaningless for GET
    $expire_time ."\n". // set the expire date of this link
    "/$path"; // full path (incl bucket), starting with a /
    
    $signature = urlencode(mymodule_constructSig($stringtosign));
    
    $url = sprintf('http://%s.s3.amazonaws.com/%s?AWSAccessKeyId=%s&Expires=%u&Signature=%s', $bucket, $filekey, S3_ACCESS_KEY_ID, $expire_time, $signature);
    
    return $url;
    }
    
    function mymodule_hex2b64($str) {
    $raw = '';
    for ($i=0; $i < strlen($str); $i+=2) {
     $raw .= chr(hexdec(substr($str, $i, 2)));
    }
    return base64_encode($raw);
    }
    
    function mymodule_constructSig($str) {
    $hasher =& new Crypt_HMAC(S3_SECRET_ACCESS_KEY, 'sha1');
    $signature = mymodule_hex2b64($hasher->hash($str));
    return $signature;
    }
    ?>
    3. Now to access a file hosted on S3, use this code. Again make sure to replace YOUR-S3-CODE.php with the name of the file you created above, YOUR-BUCKET-NAME with your Amazon bucket name, and YOU_PATH_TO_FILE with the path of the ile within your bucket:

    Code:
    <?php
      // grab this with "pear install --onlyreqdeps Crypt_HMAC"
    require_once('YOUR-S3-CODE.php');
    
    echo mymodule_get_s3_auth_link('YOUR-BUCKET-NAME', 'YOUR_PATH_TO_FILE');
    
    ?> 
    For example, if you wanted to link to a mov file in your members area you'd do somethig like this:

    Code:
    <a href="<?php echo mymodule_get_s3_auth_link('my-bucket', 'movie.mov');?>">Download Mov File</a>
    You could do the same thing to embed a streaming flv from S3.

     
    • Thanks Thanks x 3
  2. pipwaves

    pipwaves Newbie

    Joined:
    Nov 12, 2009
    Messages:
    33
    Likes Received:
    7
    Location:
    Australia
    very handy.. thanks
     
    • Thanks Thanks x 1