Я сгенерировал 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.Но все равно это не работает.