Предварительно подписанный URL-адрес AWS Ошибка PutObject: SignatureDoesNotMatch - PullRequest
0 голосов
/ 27 сентября 2019

Я сгенерировал SignedURL, который отлично работает с помощью этого кода.

const AWS = require('aws-sdk');

const s3AccessKeyId = "<my access key id>";
const s3SecretAccessKey = "<my secret access key>";
const bucketName = "<my bucket name>";

AWS.config.update({
  accessKeyId: s3AccessKeyId,
  secretAccessKey: s3SecretAccessKey,
  region: 'eu-west-1',
  signatureVersion: 'v4'
});

const s3 = new AWS.S3();

const isTokenInvalid = function (token) {
  // token validation is needed
  return token === undefined;
}

const response = function (code, body) {
  return {
    "statusCode": code,
    "headers": {'Access-Control-Allow-Origin': '*'},
    "body": body,
    "isBase64Encoded": false
  }
}

function buildDownloadParams(bucketName, key, expires) {
  return {
    Bucket: bucketName,
    Key: key,
    Expires: expires
  }
}

function buildUploadParams(bucketName, key, body, expires) {
  return {
    Bucket: bucketName,
    Key: key,
    ContentType: 'text/plain',
    ACL: 'bucket-owner-full-control',
    Body: body,
    Expires: expires
  }
}

exports.handler = (event, context, callback) => {
  const token = event.queryStringParameters["token"];
  if (isTokenInvalid(token)) {
    callback(null, response(401, "The token is not provided or is invalid."));
    return;
  }

  const action = event.queryStringParameters["action"];
  let operation;
  let params;

  if (action === 'download') {
    operation = 'getObject';
    params = buildDownloadParams(bucketName, 'video.mp4', 60);
  } else if (action === 'upload') {
    operation = 'putObject';
    params = buildUploadParams(bucketName, 'test.txt', 'hello world', 120);
  } else {
    callback(null, response(400, "ERROR: invalid action '" + action + "'"));
    return;
  }

  const preSignedGetUrl = s3.getSignedUrl(operation, params);

  callback(null, response(200, preSignedGetUrl));
};

Когда я использую PRE-SIGNED URL, все отлично работает с операцией 'getObject', но я получаю следующую ошибку при доступе кпредварительно подписанный URL с операцией putObject:

<Error>
<Code>SignatureDoesNotMatch</Code>
<Message>
The request signature we calculated does not match the signature you provided. Check your key and signing method.
</Message>
<AWSAccessKeyId>MY ACCESS KEYE</AWSAccessKeyId>
<StringToSign>
AWS4-HMAC-SHA256 20190927T094448Z 20190927/eu-west-1/s3/aws4_request ebdd9a976544557f130250f087dd596219b8e1777f292d1f2e06295df8367aa6
</StringToSign>
<SignatureProvided>
MY SIGNATURE PROVIDED
</SignatureProvided>
<StringToSignBytes>
STRING TO SIGN BYTES
</StringToSignBytes>
<CanonicalRequest>
GET /test.txt Content-Type=text%2Fplain&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=<SHA256CODE>&X-Amz-Credential=<AMZ CREDENTIALS>eu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20190927T094448Z&X-Amz-Expires=120&X-Amz-SignedHeaders=host%3Bx-amz-content-sha256 host:test-host.s3.eu-west-1.amazonaws.com x-amz-content-sha256: host;x-amz-content-sha256 UNSIGNED-PAYLOAD
</CanonicalRequest>
<CanonicalRequestBytes>
CANONICAL REQUEST BYTES
</CanonicalRequestBytes>
<RequestId>REQUEST ID</RequestId>
<HostId>
HOST ID
</HostId>
</Error>

Это конфигурация CORS в корзине AWS S3:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>

Я просмотрел все другие связанные посты в StackOverflowи исправил возможное решение, которое они упоминают, например, добавление региона, signatureVersion и ACL.Но все равно это не работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...