8

ユーザーファイルをS3にアップロードするアプリがあります。現在、フォルダとファイルのACLはプライベートに設定されています。

次の情報を格納するdbテーブル(docsと呼ばれる)を作成しました。

id
user_id
file_name (original file as specified by the user)
hash_name (random hash used to save the file on amazon)

したがって、ユーザーがファイルをダウンロードしたい場合は、最初にdbテーブルをチェックインしてファイルにアクセスできることを確認します。最初にファイルをサーバーにダウンロードしてからユーザーに送信したくないのですが、Amazonから直接ファイルを取得できるようにしたいと思います。

非常に長いハッシュ名に依存しても大丈夫ですか(ファイル名をランダムに推測することは基本的に不可能です)?この場合、各ファイルのACLを公開読み取りに設定できます。

または、ファイルを非公開にしながらファイルを提供するために使用できる他のオプションはありますか?

4

2 に答える 2

10

リンクが公開されると、ユーザーがそのリンクを他のユーザーと共有することを妨げるものは何もないことを忘れないでください。繰り返しになりますが、ユーザーがファイルを別の場所に保存し、ファイルのコピーへのリンクを共有することを妨げるものは何もありません。

最善のアプローチは、特定のニーズによって異なります。

オプション1-期間限定のダウンロードURL

シナリオに該当する場合は、S3コンテンツへの期限切れ(期間限定)のカスタムリンクを作成することもできます。これにより、ユーザーは限られた時間だけコンテンツをダウンロードでき、その後、新しいリンクを取得する必要があります。

http://docs.amazonwebservices.com/AmazonS3/latest/dev/S3_QSAuth.html

オプション2-難読化されたURL

URLがあいまいであっても意図的に共有される可能性があるというリスクを超えて、Webサーバーを介してファイルを実行することを避けることを重視する場合は、推測しにくいリンク名を使用してください。これにより、リンクを「永久に」有効なままにすることができます。つまり、リンクを「永久に」共有できます。

オプション3-サーバーからダウンロードする

リンクが共有されることを懸念していて、ユーザーがWebサイトを介して認証されることを確実に望んでいる場合は、ユーザーの資格情報を確認した後、Webサイトを介してコンテンツを提供します。

このオプションを使用すると、リンクを「永久に」有効なままにすることもできますが、リンクにアクセスするには、ユーザーがログインする必要があります(または、ブラウザーに認証Cookieがあるだけです)。

于 2012-08-14T16:27:54.400 に答える
3

誰かが同じ問題を抱えている場合は、コードを使用してPHPソリューションを投稿したいと思います。

これが私が使用したコードです:

$aws_access_key_id = 'AKIAIOSFODNN7EXAMPLE';
$aws_secret_key = 'YourSecretKey12345';
$aws_bucket = 'bucket';
$file_path = 'directory/image.jpg';
$timeout = '+10 minutes';

// get the URL!
$url = get_public_url($aws_access_key_id,$aws_secret_key,$aws_bucket,$file_path,$timeout);

// print the URL!
echo($url);



function get_public_url($keyID, $s3Key, $bucket, $filepath, $timeout)
{
    $expires = strtotime($timeout);
    $stringToSign = "GET\n\n\n{$expires}\n/{$aws_bucket}/{$file_path}";       
    $signature = urlencode(hex2b64(hmacsha1($s3Key, utf8_encode($stringToSign))));

    $url = "https://{$bucket}.s3.amazonaws.com/{$file_path}?AWSAccessKeyId={$keyID}&Signature={$signature}&Expires={$expires}";
    return $url;
}

function hmacsha1($key,$data)
{
    $blocksize=64;
    $hashfunc='sha1';
    if (strlen($key)>$blocksize)
        $key=pack('H*', $hashfunc($key));
    $key=str_pad($key,$blocksize,chr(0x00));
    $ipad=str_repeat(chr(0x36),$blocksize);
    $opad=str_repeat(chr(0x5c),$blocksize);
    $hmac = pack(
        'H*',$hashfunc(
            ($key^$opad).pack(
                'H*',$hashfunc(
                    ($key^$ipad).$data

                    )
                )
            )
        );
    return bin2hex($hmac);
}

function hex2b64($str)
{
  $raw = '';
  for ($i=0; $i < strlen($str); $i+=2)
  {
      $raw .= chr(hexdec(substr($str, $i, 2)));
  }
  return base64_encode($raw);
}
于 2013-10-23T23:01:38.620 に答える