You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

部署后使用AWS S3预签名POST URL上传图片提示InvalidAccessKeyId错误,本地测试正常

解决S3预签名POST部署后InvalidAccessKeyId错误

兄弟,我刚好碰到过一模一样的问题!咱们先把问题根儿找清楚:你本地用的是长期IAM访问密钥(AKIA开头),但部署到Lambda之后,函数用的是IAM角色给的临时凭证(ASIA开头)。临时凭证必须带X-Amz-Security-Token才能被S3认,但你的代码里没把这个token加到预签名POST的表单字段里,这就导致了权限验证失败。

为啥DynamoDB能正常跑?

这是因为AWS SDK对DynamoDB这类客户端特别友好——它会自动从Lambda的执行环境里捞到完整的临时凭证(包括session token),请求的时候自动带上。但createPresignedPost这个方法比较“直男”,不会自动把session token塞进POST的表单里,得咱们手动加。

具体怎么改?

  1. 给预签名POST加Session Token
    修改你的createUrl函数,在Fields里加上X-Amz-Security-Token——Lambda环境会自动把这个值放到process.env.AWS_SESSION_TOKEN里,咱们直接拿就行。

    改完的代码是这样的:

    public createUrl(filename: string): Promise<any> { // 这里注意返回类型,原先是string但实际返回的是带url和fields的对象
      return new Promise((resolve, reject) => {
        const postParams = {
          Bucket: "{{bucket-name}}",
          Fields: {
            key: filename,
          },
          Conditions: [
            ["content-length-range", 0, 1048576],
            ["starts-with", "$Content-Type", "image/"],
          ],
          Expires: 120,
        };
    
        // 有临时token就加上,本地测试的时候这个变量不存在,不会影响
        if (process.env.AWS_SESSION_TOKEN) {
          postParams.Fields['X-Amz-Security-Token'] = process.env.AWS_SESSION_TOKEN;
        }
    
        this.s3.createPresignedPost(postParams, (error, data) => {
          if (error) reject(error);
          else resolve(data);
        });
      });
    }
    

    对了,你原来的函数返回类型标了Promise<string>,但createPresignedPost返回的是包含url和fields的对象,这个得改一下,不然TypeScript会报错。

  2. 检查IAM角色和桶的CORS
    先确认你的Lambda执行角色有s3:PutObject权限(针对目标存储桶)。另外,桶的CORS配置得允许你的前端域名发POST请求,比如:

    <CORSConfiguration>
      <CORSRule>
        <AllowedOrigin>https://你的前端域名.com</AllowedOrigin>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
      </CORSRule>
    </CORSConfiguration>
    
  3. 验证返回结果
    部署完再调用接口,看看返回的fields里有没有X-Amz-Security-Token字段。有的话,前端上传的时候把这个字段和其他表单数据一起提交给S3的URL就行。

补充一句

长期密钥(AKIA)不需要session token,所以本地测啥问题没有;但临时凭证(ASIA)必须带这个token,S3才认。而且AWS SDK的createPresignedUrl(GET请求用的)会自动处理token,但createPresignedPost就得手动加,这坑我当初踩了好久!

内容的提问来源于stack exchange,提问作者matikowy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 00:19:08