2012-08-14 28 views
8

Tôi có một ứng dụng tải tệp người dùng lên S3. Hiện tại, ACL cho các thư mục và tệp được đặt thành riêng tư.Phân phối an toàn các tệp từ Amazon S3

Tôi đã tạo ra một bảng db (gọi tắt là tài liệu) mà các cửa hàng các thông tin sau:

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

Vì vậy, khi người dùng muốn tải về một tập tin, lần đầu tiên tôi kiểm tra trong bảng db rằng họ có quyền truy cập vào tập tin. Tôi không muốn có tập tin đầu tiên tải về máy chủ của tôi và sau đó gửi cho người dùng - Tôi muốn họ có thể lấy các tập tin trực tiếp từ Amazon.

Có OK để dựa vào một tên băm rất dài (làm cho về cơ bản không thể cho bất kỳ ai đoán ngẫu nhiên tên tệp)? Trong trường hợp này, tôi có thể đặt ACL cho mỗi tệp để đọc công khai.

Hoặc, có những tùy chọn nào khác mà tôi có thể sử dụng để phân phối tệp trong khi vẫn giữ riêng tư không?

Trả lời

9

Hãy nhớ rằng, khi liên kết ở ngoài đó, không có gì ngăn người dùng chia sẻ liên kết đó với người khác. Sau đó, một lần nữa, không có gì ngăn cản người dùng lưu tệp ở nơi khác và chia sẻ liên kết tới bản sao của tệp.

Cách tiếp cận tốt nhất tùy thuộc vào nhu cầu cụ thể của bạn.

Lựa chọn 1 - Thời gian Limited Tải URL

Nếu áp dụng đối với trường hợp của bạn, bạn cũng có thể tạo liên kết hết hạn tùy chỉnh (giới hạn thời gian) với các nội dung S3. Điều đó sẽ cho phép người dùng tải xuống nội dung trong một khoảng thời gian giới hạn, sau đó họ sẽ phải có được một liên kết mới.

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

Lựa chọn 2 - bị xáo trộn URL

Nếu bạn đánh giá cao tránh chạy các tập tin thông qua máy chủ web của bạn so với rủi ro mà một URL, tuy nhiên mơ hồ, có thể được chia sẻ cố ý, sau đó sử dụng cứng tên liên kết để đoán. Điều này sẽ cho phép một liên kết vẫn còn hiệu lực "mãi mãi", có nghĩa là liên kết có thể được chia sẻ "mãi mãi".

Tùy chọn 3 - Tải qua máy chủ của bạn

Nếu bạn lo lắng về liên kết được chia sẻ và chắc chắn muốn người dùng để xác thực thông qua trang web của bạn, sau đó cung cấp nội dung thông qua trang web của bạn sau khi xác minh thông tin người dùng.

Tùy chọn này cũng cho phép liên kết vẫn hợp lệ "mãi mãi" nhưng yêu cầu người dùng đăng nhập (hoặc có thể chỉ có cookie xác thực trong trình duyệt) để truy cập liên kết.

+0

Vì vậy, về cơ bản, không có cách nào để giữ ACL tư nhân và vẫn phục vụ nó từ amazon? Điều gì về tạm thời thay đổi ACL để đọc công khai, sau đó phục vụ nó từ S3, và sau đó thay đổi ACL trở lại tư nhân? – JonoB

+0

Xem câu trả lời cập nhật của tôi. Bạn có thể tạo URL công khai giới hạn thời gian trong khi không mở ACL của bạn với mọi người. –

+0

@EricJ.tôi có thể biết làm thế nào để làm cho nó được xác thực người dùng để xem hình ảnh. Nếu bạn biết sau đó bạn có thể trả lời cho câu hỏi này http://stackoverflow.com/questions/40168221/laravel-secure-amazon-s3-bucket-files.Cảm ơn bạn – iCoders

2

Tôi chỉ muốn đăng giải pháp PHP bằng mã, nếu có ai có cùng vấn đề.

Dưới đây là đoạn code tôi sử dụng:

$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); 
} 
+0

Câu trả lời chính xác. Làm việc hoàn hảo. Cảm ơn bạn Josue! –

Các vấn đề liên quan