【问题标题】:AWS S3 Bucket - getSignedUrl PUT return a 400 (Bad Request)AWS S3 存储桶 - getSignedUrl PUT 返回 400(错误请求)
【发布时间】:2019-03-30 16:22:19
【问题描述】:

我的项目中有一个奇怪的问题是我无法找到我做错了什么。我正在尝试将图像上传到我的博客,并且我正在使用 aws s3 配置来执行此操作。我相信我的配置是正确的,但以防万一我将它们添加到那里:

这是我的 cors 配置

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

我的所有 IAM 策略和用户 api 都已按顺序进行并已激活。这是我后端的代码:

const s3 = new AWS.S3({
  accessKeyId: keys.aws.clientID,
  secretAccessKey: keys.aws.clientSecret,
  signatureVersion: "v4",
  region: "eu-west-3"
})

const router = express.Router()
// @route  GET api/posts/upload
// @desc   Upload an image on amazone server API
// @access Private
router.get(
  "/upload",
  passport.authenticate("jwt", { session: false }),
  (req, res) => {
    const key = `${req.user.id}/${uuid()}.jpeg`
    s3.getSignedUrl(
      "putObject",
      {
        Bucket: "bebeyogini",
        ContentType: "image/jpeg",
        Key: key
      },
      (err, url) => res.send({ key, url })
    )
  }
)

当我调用 /upload 端点时,它返回一个

<Error>
<Code>SignatureDoesNotMatch</Code>
<Message>
The request signature we calculated does not match the signature you provided. Check your key and signing method.
</Message>

这就是为什么在我的前端(在 redux 中)我添加了一个 PUT,我在标题中添加了内容类型文件。但是在这个项目中还是不行

export const sendPost = (newPost, file, history) => async dispatch => {
  dispatch(loading())
  const uploadConfig = await axios.get("/api/posts/upload")
  console.log(uploadConfig)
  console.log(uploadConfig.data)
  await axios.put(uploadConfig.data.url, file, {
    headers: {
      "Content-Type": file.type
    }
  })
  const res = await axios.post("/api/posts", {
    ...newPost,
    imageUrl: uploadConfig.data.key
  })
  history.push("/dashboard")
  dispatch({
    type: POSTS_FETCHED,
    payload: res.data
  })
}

几个月前,我在另一个项目中取得了成功,使 aws s3 工作做这些相同的配置,我在两者之间的唯一区别是解决的一个是使用 cookie 会话设置的,而这个是一个 jwt-token在标题中。

如果有人有想法...我完全被卡住了! 这里是存储库

错误状态:

bebeyogini.s3.eu-west-3.amazonaws.com/5bc0eca10743075fecb360f2/8bb4ff60-d8e7-11e8-ad9d-f776f418fd42.jpeg?Content-Type=image%2Fjpeg&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIAMYTIX267RJ5E4A%2F20181026%2Feu-west-3%2Fs3%2Faws4_request&X-Amz-Date=20181026T062242Z&X-Amz-Expires=900&X-Amz-Signature=943652af4bea7e8e0e6d0f97503ea997817e7d68e0540c599643d612d71fe693&X-Amz-SignedHeaders=host:1 PUT https://bebeyogini.s3.eu-west-3.amazonaws.com/5bc0eca10743075fecb360f2/8bb4ff60-d8e7-11e8-ad9d-f776f418fd42.jpeg?Content-Type=image%2Fjpeg&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIAMYTIX267RJ5E4A%2F20181026%2Feu-west-3%2Fs3%2Faws4_request&X-Amz-Date=20181026T062242Z&X-Amz-Expires=900&X-Amz-Signature=943652af4bea7e8e0e6d0f97503ea997817e7d68e0540c599643d612d71fe693&X-Amz-SignedHeaders=host 400 (Bad Request)
createError.js:17 Uncaught (in promise) Error: Request failed with status code 400
    at createError (createError.js:17)
    at settle (settle.js:19)
    at XMLHttpRequest.handleLoad (xhr.js:78)

https://github.com/erwanriou/bebeyogini

【问题讨论】:

标签: node.js amazon-web-services amazon-s3 redux jwt


【解决方案1】:

好吧,经过几个晚上的痛苦,我确实找到了问题的解决方案。请注意,AWS S3 不接受其 PUT 请求中包含的 jwt 不记名令牌。因此,您必须在执行请求时禁用它。在这里,我可以使用库 axios 在我的前端修复它...

export const sendPost = (values, file, history) => async dispatch => {
  dispatch(loading())
  const uploadConfig = await axios.get("/api/posts/upload")
  delete axios.defaults.headers.common["Authorization"]
  await axios.put(uploadConfig.data.url, file, {
    headers: {
      ContentType: file.type
    }
  })
  const token = localStorage.getItem("jwtToken")
  axios.defaults.headers.common["Authorization"] = token
  const res = await axios.post("/api/posts", {
    ...values,
    imageUrl: uploadConfig.data.key
  })
  dispatch({
    type: POSTS_FETCHED,
    payload: res.data
  })
  history.push("/dashboard")
}

【讨论】:

  • 这解决了我的问题。我使用的是 Nuxt 内置的 $axios 模块,其中包括 Authorization 标头。我必须导入并创建一个新的 axios 实例。
  • 这节省了我的时间。
  • 这可能为我节省了数小时的工作时间。谢谢。
【解决方案2】:

The request signature we calculated does not match the signature you provided. Check your key and signing method.这意味着您的预签名数据与您要上传的数据不匹配。

您的签名数据:

{
    Key: `${req.user.id}/${uuid()}.jpeg`
    ContentType: "image/jpeg",
}

您的文件元数据:

{
    Name: file.name
    ContentType: "image/jpeg",
}

file.name !== ${req.user.id}/${uuid()}.jpeg

您可以将客户端的文件名更改为服务器端的相同文件名(已生成的文件名),或使用相反的方式

【讨论】:

  • 我明白了,这可以解释很多!我会尽快更新!
  • 好吧,我看,我只是想不通你怎么能说我的文件元是 file.name 我一次又一次地验证,我不知道你所说的名称是什么意思:file.name
  • sendPost 函数在你的前端,第二个参数命名为 - file。这是一个文件对象,file.name 是文件的原始名称(从您的计算机上传的文件)。
  • 好的,在操作中我使用的 PUT 函数作为第一个参数 uploadConfig.data.url 我想上传数据,然后你说在我的第二个参数中是文件,它会自动检测我不想让他检测到的 file.name 事件吗?我确实尝试通过转换 key = 'test.jpeg' 在后端设置完全相同的名称并导入一个名为 'test.jpeg' 的图像以匹配此文件名,但我确实遇到了同样的错误。
  • 问题是,使用完全相同的 UI 和后端,但使用 cookie 而非 jwt 令牌设置身份验证,它可以完美地工作。但我想要 jwt,因为我不想只在导航器上这样做......我不知道为什么,但我认为授权标头正在做一些奇怪的事情,而 aws s3 不喜欢它。
猜你喜欢
  • 2019-04-29
  • 2019-07-28
  • 1970-01-01
  • 2022-07-16
  • 2020-08-06
  • 1970-01-01
  • 2015-07-05
  • 2021-06-17
  • 1970-01-01
相关资源
最近更新 更多