【问题标题】:putObject to Public S3 BucketputObject 到公共 S3 存储桶
【发布时间】:2021-06-30 19:34:35
【问题描述】:

我有一个 API 调用的 lambda,它生成签名的 getObject 和 putObject URL。我的受限存储桶(包含 zip 文件)上的 GET 和 PUT 工作正常,但我的公共存储桶(包含图像)上的 PUT 会返回“SignatureDoesNotMatch”错误。公共存储桶上没有 GET,直接引用来自该存储桶的图像。我是否需要额外的配置才能将 PUT 放在公共存储桶上?我已经尝试过给予我能想到的最慷慨的权限。

编辑:我最终不得不将特定图像 MIME 类型发送到生成签名 URL 的端点。不幸的是,image/* 不起作用。

签名 URL 生成(由 getSignedImgUploadUrl 调用)

let params = {
    Bucket: "public-bucket",
    Key: `${folder}/${key}.jpg`, // Ideally without extension
    Expires: 30,
    ContentType: "image/jpeg", // Ideally image/*
    ACL: "public-read" // Tried with and without this
};
let url = s3.getSignedUrl("putObject", params);
let result = {
    signedUrl: url,
    key: key
};
return result;

使用签名网址

  public uploadImg(folder: string, file: any, key: string): Observable<any> {
    return this._spinnerService.spinObservable(
      new Observable(subscriber => {
        this.getSignedImgUploadUrl(folder, key)
          .subscribe(result => {
            // put to signedUrl fails with 403 SignatureDoesNotMatch
            this._httpClient.put(result["signedUrl"], file, { headers: { "x-amz-acl": "public-read" } })
              .subscribe(() => {
                subscriber.next(result["key"]);
                subscriber.complete();
              }, err => {
                console.log(err);
                subscriber.error(err);
              });
          }, err => {
            console.log(err);
            subscriber.error(err);
          });
      }));
  }

Lambda 角色

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::restricted-bucket/*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "s3:ListAllMyBuckets"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor2",
            "Effect": "Allow",
            "Action": "s3:*", (Ideally just getObject/putObject)
            "Resource": "arn:aws:s3:::public-bucket/*"
        }
    ]
}

公共存储桶政策

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::public-bucket/*"
        },
        // Also tried adding s3:* for the lambda role without luck
        {
            "Sid": "Stmt1624999949645",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::account:role/service-role/lambda-role"
            },
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::public-bucket/*"
        }
    ]
}

【问题讨论】:

  • 能否也显示上传对象的代码?
  • 当然!我从 UI 添加了代码,我首先在其中获取签名的 url,然后尝试将图像放入其中。我最近尝试使用 acl 标头,但这并没有什么不同。
  • 尝试在客户端显式发送Content-Type 标头。
  • 嗯......这完全有效。为什么您认为公共存储桶/图像类型需要 Content-Type 客户端而不是 zips?

标签: amazon-web-services amazon-s3 aws-lambda


【解决方案1】:

根据 OP 的评论,明确发送 Content-Type HTTP 标头有效。有时需要此标头的原因是 HTTP 客户端无法从 PUT 负载中正确推断 MIME 类型。

【讨论】:

    猜你喜欢
    • 2017-03-07
    • 2016-11-16
    • 2014-12-23
    • 1970-01-01
    • 1970-01-01
    • 2019-02-21
    • 1970-01-01
    • 1970-01-01
    • 2017-12-30
    相关资源
    最近更新 更多