Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing private s3 bucket files

I am uploading files from php to s3 bucket.its uploading successfully but when i retrieve image i get following error

<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<Expires>2006-03-09T07:25:20Z</Expires>
<ServerTime>2016-11-05T04:38:24Z</ServerTime>

if i set public when uploading files then i can retrieve it but i wanted to protect from unauthorized users.

upload file code

try{
    $s3 = \Storage::disk('s3');
    $filePath = $file->getClientOriginalName();
    $s3->put($filePath, file_get_contents($val), 'private');

    } catch (Aws\Exception\S3Exception $e) {
        echo "There was an error uploading the file.\n"+$e;
    }

Before asking question i have refereed many websites but it didnt helped me

Amazon S3 see private files

PHP Amazon S3 access private files through URL

How to access Amazon s3 private bucket object through Zend_Service_Amazon_S3

Third link is working for me but

1.is it secure to pass access key in url ?

2.is possible to view that file to authenticated user ?

public function get_s3_signed_url($bucket, $resource, $AWS_S3_KEY, $AWS_s3_secret_key, $expire_seconds) {
     $expires = time()+$expire_seconds;
     // S3 Signed URL creation
     $string_to_sign = "GET\n\n\n{$expires}\n/".str_replace(".s3.amazonAWS.com","", $bucket)."/$resource";
     $signature = urlencode(base64_encode((hash_hmac("sha1", utf8_encode($string_to_sign), $AWS_s3_secret_key, TRUE))));

     $authentication_params = "AWSAccessKeyId=".$AWS_S3_KEY;
     $authentication_params.= "&Expires={$expires}";
     $authentication_params.= "&Signature={$signature}";
     return $link = "http://s3.amazonAWS.com/{$bucket}/{$resource}?{$authentication_params}";
}
like image 727
Vision Coderz Avatar asked Nov 05 '16 04:11

Vision Coderz


1 Answers

Here get_s3_signed_url function returns the url which has access key and it is not recommended. Make a function where it gets the private object object from the bucket and creates a file/an image locally in the server. Use the path of newly created image and delete the image once you are done with it.

Code in Zend:

require_once('Zend/Service/Amazon/S3.php');

$awsKey = 'your-key';
$awsSecretKey = 'your-secret-key';

$s3 = new Zend_Service_Amazon_S3($awsKey, $awsSecretKey);

$bucketName = 'your-bucket-name';
$objectName = $bucketName . '/image.jpg'; //image path

$info = $s3->getInfo($objectName);

if (is_array($info)) {
    header('Content-type: ' . $info['type']);
    header('Content-length: ' . $info['size']);

    file_put_contents('image.jpg', file_get_contents($s3->getObject($objectName)));

    header('Content-Description: File Transfer');
    header("Content-Disposition: attachment; filename=\"image.jpg\"");
    header('Content-Transfer-Encoding: binary');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Expires: 0');
    ob_clean();
    flush();
    readfile('image.jpg');
    unlink('image.jpg');
} else {
    header('HTTP/1.0 404 Not Found');
}


Code in core php:

require_once('S3.php');

$awsKey = 'your-key';
$awsSecretKey = 'your-secret-key';

$s3 = new S3($awsKey, $awsSecretKey);

$bucketName = 'your-bucket-name';


** To store/download one image at a time**

$objectName = "image.jpg"; //s3 image path
$tempFile = "image.jpg"; //temporary/local image path

$s3->getObject($bucketName, $objectName, $tempFile); //stores the image 

if (filesize($tempFile)) {
    header('Content-Description: File Transfer');
    header('Content-Type: image/png');
    header("Content-Disposition: attachment; filename=\"" . $tempFile . "\"");
    header('Content-Transfer-Encoding: binary');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Expires: 0');
    header('Content-Length: ' . filesize($tempFile));
    ob_clean();
    flush();
    readfile($tempFile); //downloads the image
    unlink($tempFile); //deletes the image from local 
}

**To store/download 'n' images at a time**

$s3ImagesFolder = 'all_images/'; //folder where all the images are 

$bucketContents = $s3->getBucket($bucketName);

foreach ($bucketContents as $file) {

if ((strpos($file['name'], $s3ImagesFolder) > -1)) {
    $tempFile = end(explode("/", $file['name']));
    $s3->getObject($bucketName, $file['name'], $tempFile); // to store 

    //to download
    if ($file['size']) {
        header('Content-Description: File Transfer');
        header('Content-Type: image/png');
        header("Content-Disposition: attachment; filename=\"" . $tempFile . "\"");
        header('Content-Transfer-Encoding: binary');
        header('Cache-Control: must-revalidate');
        header('Pragma: public');
        header('Expires: 0');
        header('Content-Length: ' . $file['size']);
        ob_clean();
        flush();
        readfile($tempFile); //downloads the image
        unlink($tempFile); //deletes the image from local 
    }
  }
}
like image 111
MurthyAdapa Avatar answered Nov 18 '22 17:11

MurthyAdapa