【问题标题】:Multipart upload with presigned urls - Scaleway S3-compatible object storage使用预签名 url 进行分段上传 - Scaleway S3 兼容的对象存储
【发布时间】:2022-01-07 04:56:07
【问题描述】:

我正在尝试使用预签名的 url 在 Scaleway 对象存储(S3 兼容)上进行分段上传,并且在浏览器生成的预检请求中出现错误 (403),但我的 CORS 设置似乎正确设置。 (基本上是允许的标头和来源上的通配符)。

该错误带有 403 状态代码,如下所示:

<?xml version='1.0' encoding='UTF-8'?>
<Error><Code>AccessDenied</Code><Message>Access Denied.</Message><RequestId>...</RequestId></Error>

我在这个问题上停留了一段时间,我尝试从浏览器复制飞行前请求以在其他地方重现它,并尝试对其进行一些调整。 从飞行前请求的 url 中删除查询参数使请求成功(返回 200 并正确设置了 Access-Control-Allow-* 响应标头)但这显然不是浏览器行为...

这不起作用(密码、密钥和名称已更改)

curl 'https://bucket-name.s3.fr-par.scw.cloud/tmp-screenshot-2021-01-20-at-16-21-33.png?AWSAccessKeyId=XXXXXXXXXXXXXXXXXXXX&Expires=1638217988&Signature=NnP1XLlcvPzZnsUgDAzm1Uhxri0%3D&partNumber=1&uploadId=OWI1NWY5ZGrtYzE3MS00MjcyLWI2NDAtNjFkYTM1MTRiZTcx' -X OPTIONS -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:94.0) Gecko/20100101 Firefox/94.0' -H 'Accept: */*' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Referer: http://domain.tech/' -H 'Access-Control-Request-Method: PUT' -H 'Origin: http://domain.tech' -H 'DNT: 1' -H 'Connection: keep-alive' -H 'Sec-Fetch-Dest: empty' -H 'Sec-Fetch-Mode: no-cors' -H 'Sec-Fetch-Site: cross-site' -H 'Pragma: no-cache' -H 'Cache-Control: no-cache'

This Works(秘密、密钥和名称已更改)

curl 'https://bucket-name.s3.fr-par.scw.cloud/tmp-screenshot-2021-01-20-at-16-21-33.png' -X OPTIONS -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:94.0) Gecko/20100101 Firefox/94.0' -H 'Accept: */*' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Referer: http://domain.tech/' -H 'Access-Control-Request-Method: PUT' -H 'Origin: http://domain.tech' -H 'DNT: 1' -H 'Connection: keep-alive' -H 'Sec-Fetch-Dest: empty' -H 'Sec-Fetch-Mode: no-cors' -H 'Sec-Fetch-Site: cross-site' -H 'Pragma: no-cache' -H 'Cache-Control: no-cache'

url 来自aws-sdk 并以这种方式生成:

const S3Client = new S3({
  credentials: {
    accessKeyId: env.SCW_ACCESS_KEY,
    secretAccessKey: env.SCW_SECRET_KEY,
  },
  endpoint: `https://s3.${env.SCW_REGION}.scw.cloud`,
})

S3Client.getSignedUrlPromise('uploadPart', {
    Bucket: bucket,
    Key: key,
    UploadId: multipartUpload.UploadId,
    PartNumber: idx + 1,
})

并在前端使用这种方式:

// url being the url generated in backend as demonstrated above
const response = await fetch(url, {
  method: 'PUT',
  body: filePart,
  signal: abortController.signal,
})

如果有人能帮我解决这个或那个,那就太好了!

【问题讨论】:

    标签: amazon-web-services amazon-s3 file-upload pre-signed-url


    【解决方案1】:

    事实证明,Scaleway 对象存储在这种情况下并不完全兼容 S3。
    这是一个解决方法:

    • 安装aws4库以轻松签署请求(或关注this scaleway doc手动签署您的请求)
    • 完全按照this other scaleway doc 中的说明形成您的请求(这是aws-sdk 行为不同的地方,它会生成一个带有AWSAccessKeyIdExpiresSignature 查询参数的url,这会导致scaleway API 失败。 Scaleway API 只需要partNumberuploadId)。
    • 将生成的url和headers返回给前端
    // Backend code
    const signedRequest = aws4.sign(
      {
        method: 'PUT',
        path: `/${key}?partNumber=${idx + 1}&uploadId=${
          multipartUpload.UploadId
        }`,
        service: 's3',
        region: env.SCW_REGION,
        host: `${bucket}.s3.${env.SCW_REGION}.scw.cloud`,
      },
      {
        accessKeyId: env.SCW_ACCESS_KEY,
        secretAccessKey: env.SCW_SECRET_KEY,
      },
    )
    
    return {
      url: `https://${signedRequest.host}${signedRequest.path}`,
      headers: Object.keys(signedRequest.headers).map((key) => ({
        key,
        value: signedRequest.headers[key] as string,
      })),
    }
    

    然后在前端:

    // Frontend code
    const headers = signedRequest.headers.reduce<Record<string, string>>(
      (acc, h) => ({ ...acc, [h.key]: h.value }),
      {},
    )
    
    const response = await fetch(signedRequest.url, {
      method: 'PUT',
      body: filePart,
      headers,
      signal: abortController.signal,
    })
    

    Scaleway 知道这个问题,因为我直接与他们的支持团队讨论过,他们正在努力以尽可能地符合 S3。在您阅读本文时,此问题可能已解决。 感谢他们的快速响应和认真对待。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-15
      • 2021-02-15
      • 2021-10-25
      • 2021-09-09
      • 1970-01-01
      • 2020-08-13
      • 2019-01-30
      • 1970-01-01
      相关资源
      最近更新 更多