首页 文章

安全地从Amazon S3提供文件

提问于
浏览
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表中检查他们是否有权访问文件 . 我宁愿不先将文件下载到我的服务器然后发送给用户 - 我希望他们能够直接从亚马逊获取文件 .

是否可以依赖非常长的hashname(任何人都无法随机猜出文件名)?在这种情况下,我可以将每个文件的ACL设置为public-read .

或者,我可以使用其他选项来提供文件,同时保持文件的私密性吗?

2 回答

  • 9

    我只是想用代码发布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);
    }
    
  • 2

    请记住,一旦链接在那里,没有什么可以阻止用户与他人共享该链接 . 然后,没有什么能阻止用户将文件保存到别处并共享指向文件副本的链接 .

    最好的方法取决于您的具体需求 .

    Option 1 - Time Limited Download URL

    如果适用于您的方案,您还可以创建到S3内容的过期(有时间限制)自定义链接 . 这将允许用户在有限的时间内下载内容,之后他们将不得不获得新的链接 .

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

    Option 2 - Obfuscated URL

    如果您重视通过Web服务器运行文件,而不是有意识地共享URL(无论多么模糊),那么请使用难以猜测的链接名称 . 这将允许链接“永远”保持有效,这意味着链接可以“永久”共享 .

    Option 3 - Download through your server

    如果您担心要共享的链接并且当然希望用户通过您的网站进行身份验证,请在验证用户凭据后通过您的网站提供内容 .

    此选项还允许链接“永久”保持有效,但要求用户登录(或者可能只是在浏览器中有一个身份验证cookie)才能访问该链接 .

相关问题