Как получить доступ к изображению в ведре s3, используя предварительно подписанный URL-адрес

Я хочу получить доступ к изображению, хранящемуся в корзине s3, с использованием предварительно подписанного URL-адреса. Это изображение должно иметь доступ к тому, у кого есть предварительно подписанный URL-адрес. Пожалуйста, помогите мне решить эту проблему.

Я понятия не имею, какую подпись он получает. Если он получает мою подпись, то как это работает для других пользователей. Пожалуйста, помогите мне

Когда я это делаю. Он покажет эту ошибку

<Error>
<Code>SignatureDoesNotMatch</Code>
    </Message>
    <AWSAccessKeyId>XX</AWSAccessKeyId>
    <StringToSign>GET 1900675866 /bucketname/161305.jpg</StringToSign>
    <SignatureProvided>xxxx</SignatureProvided>
    <StringToSignBytes>
    47 45 54 0a 0a 0a 31 39 30 30 36 37 35 38 36 36 0a 2f 6b 6c 70 2d 6d 65 64 69 61 2f 31 36 31 33 30 35 2e 6a 70 67
    </StringToSignBytes>
    <RequestId>xxxxx</RequestId>
    <HostId>
    xxxx
    </HostId>
    </Error>

Вот код, который я пытался сгенерировать с предварительно подписанным URL-адресом

exports.handler = async function (event, context) {
    console.log('strarting to generate pre-signed image url');

     let s3BucketName = process.env.S3_BUCKET_NAME;
    const request = JSON.parse(event.body);
    const objectKey = request.key;
    const studentId = request.studentId;
    console.log(' generate pre-signed image url for:' + objectKey);

    console.log('Started getting pre signed url for:' + objectKey);

    let params = {
        Bucket: s3BucketName,
        Key: objectKey,
        Expires: 60 * 60 * 24 * 365 * 10,
        ContentType: 'image/jpg'
    };
    return await s3.getSignedUrlPromise('putObject', params).then(async url => {
        console.log('Successfully generated pre signed image url', url);
         const payload = {
            message: 'success',
            imageUrl: url
        };
        const response = {
            statusCode: 201,
            headers: responseHeaders,
            body: JSON.stringify(payload),
        };
        return response;
    }).catch(error => {
        console.error(`Failed to generate presigned url: ${error}`);
        return {
            statusCode: error.statusCode || 501,

            headers: responseHeaders,
            body: JSON.stringify({
                message: `Failed to generate presigned url. Request Id: ${context.awsRequestId}`
            })
        };
    });


}

На стороне aws я заблокировал весь публичный доступ. Вот политика ведра

{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Sid": "AllowPublicRead",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::media/*"
        }
    ]
}

person DevAra    schedule 30.03.2020    source источник


Ответы (3)


Вы пытаетесь создать предварительно подписанный URL-адрес для PutObject. Вместо этого попробуйте "GetObject"

person vijilvpillai712    schedule 10.04.2020

есть два метода, с помощью которых вы можете использовать Pre Sign-in URL. так же, как я использую в своем проекте.

  1. $path : где вы храните или загружаете файл.

  2. $disk: name — это диск, который вы используете в laravel. нравится ( с3 )

    function  getS3PreSignURL($path ,$disk)
     {
       $s3 = \Storage::disk($disk);
       $client = $s3->getDriver()->getAdapter()->getClient();
       $expiry = "+5 minutes";
       $command = $client->getCommand('GetObject', [
      'Bucket' => Config::get('filesystems.disks.'.$disk.'.bucket'),
      //'Key'    => "uploads/1***1/image/030685.jpeg"
      'Key'    => $path
     ]);
     $request = $client->createPresignedRequest($command, $expiry);
     return (string) $request->getUri();
    } 
    
    
    function getS3StreamUrl($path , $disk)
    {
      $s3 = \Storage::disk($disk);
      $s3->getDriver()->getAdapter()->getClient()->registerStreamWrapper();
       return $fileUrl = "s3://".env("AWS_BUCKET").'/'.$path;
       if (is_file($fileUrl) && file_exists($fileUrl)) {
         return $fileUrl;
       } else {
          return false;
        }
      }
    

getS3StreamUrl будет использоваться при создании FPDF pdf. потому что getS3PreSignURL возвращает токен AWS в ссылке, поэтому он не будет работать в FPDF.

person pankaj kumar    schedule 31.07.2020

Весь смысл предварительно подписанного URL-адреса заключается в предоставлении временного доступа к объектам в ведре s3. вам не нужно создавать учетные данные aws и предоставлять доступ.

Предварительно подписанный URL-адрес создается с использованием учетных данных AWS (AccessKeyId, SecretAccessKeyId) пользователя (в данном случае вас), у которого есть доступ к определенной операции s3, такой как GetObject или PutObject. После того, как URL-адрес сгенерирован, URL-адрес может быть доступен любому через Интернет. Предварительно подписанный URL-адрес действителен только в течение определенного времени. Если вы не указали срок действия, он истечет через 7 дней.

При доступе к предварительно подписанному URL-адресу AWS вычислит подпись на их конце, а затем сравнит это значение подписи с подписью, переданной в URL-адресе.

В этом случае, как сказал @vijilvpillai712, вы создаете предварительно подписанный URL-адрес для putObject и пытаетесь получить доступ через HTTP GetObject.

для типа контента используйте content/jpeg, а не content/jpg. это правильный тип пантомимы. Но это не имеет никакого отношения к вашей проблеме.

person Arun K    schedule 31.07.2020