使用 SSE 对 S3 对象的预签名 url 进行 GET 请求失败,并出现 403 错误

当我向 Go 中的GETAWS 方法生成的预签名 URL 发出请求时,收到 403 Forbidden HTTP 响应。Presign

错误信息是:

我们计算的请求签名与您提供的签名不匹配。检查您的密钥和签名方法

X-Amz-SignedHeaders是:host;x-amz-server-side-encryption-customer-algorithm;x-amz-server-side-encryption-customer-key;x-amz-server-side-encryption-customer-key-md5

我将对象写入 S3,如下所示:

type DocumentStore struct {

    bucketName               string

    bucketEncryptionKeyAlias string

    aws                      *session.Session

}


func (s *DocumentStore) PutDocument(ctx context.Context, envelope []byte, metadata map[string]string) (PutDocumentResult, error) {

    uploader := s3manager.NewUploader(s.aws)


    var objectKey = uuid.New().String()


    if _, err := uploader.UploadWithContext(ctx, &s3manager.UploadInput{

        Bucket:               aws.String(s.bucketName),

        Key:                  aws.String(objectKey),

        ContentType:          aws.String("application/octet-stream"),

        Body:                 bytes.NewReader(envelope),

        ServerSideEncryption: aws.String(s3.ServerSideEncryptionAwsKms),

        SSEKMSKeyId:          aws.String(s.bucketEncryptionKeyAlias),

        Metadata:             aws.StringMap(metadata),

    }); err != nil {

        return PutDocumentResult{}, fmt.Errorf("put document failed on upload: %v", err.Error())

    }


    return PutDocumentResult{

        BucketName: s.bucketName,

        ObjectKey:  objectKey,

    }, nil

}

我像这样签署网址:


func (s *DocumentStore) NewSignedGetURL(ctx context.Context, objectKey string, ttl time.Duration) (string, error) {

    svc := s3.New(s.aws)


    req, _ := svc.GetObjectRequest(&s3.GetObjectInput{

        Bucket: aws.String(s.bucketName),

        Key: aws.String(objectKey),

        SSECustomerKey: aws.String(s.bucketEncryptionKeyAlias),

        SSECustomerAlgorithm: aws.String(s3.ServerSideEncryptionAwsKms),

    })


    url, err := req.Presign(ttl)

    if err != nil {

        return "", fmt.Errorf("failed to presign GetObjectRequest for key %q: %v", objectKey, err)

    }


    return url, nil

}

我缺少什么?


森栏
浏览 112回答 1
1回答

HUWWW

我发现:GetObject只要用户拥有DecryptKMS 密钥的权限,请求就不需要 SSE 参数。以下是相关变更:我现在正在像这样签署网址:func (s *DocumentStore) NewSignedGetURL(ctx context.Context, objectKey string, ttl time.Duration) (string, error) {    svc := s3.New(s.aws)    req, _ := svc.GetObjectRequest(&s3.GetObjectInput{        Bucket: aws.String(s.bucketName),        Key: aws.String(objectKey),    })    url, err := req.Presign(ttl)    if err != nil {        return "", fmt.Errorf("failed to presign GetObjectRequest for key %q: %v", objectKey, err)    }    return url, nil}我正在下载这样的对象:getURL, err := target.NewSignedGetURL(context.TODO(), result.ObjectKey, time.Minute*5)if err != nil {    t.Errorf("failed to sign url: %v", err)    return}req, _ := http.NewRequest("GET", getURL, nil)req.Header.Add("host", req.Host)resp, err := http.DefaultClient.Do(req.WithContext(context.TODO()))if err != nil {    t.Errorf("failed to request object from signed url: %v", err)    return}defer resp.Body.Close()data, err := ioutil.ReadAll(resp.Body)if err != nil {    t.Errorf("failed to read object stream from S3: %v", err)    return}
打开App,查看更多内容
随时随地看视频慕课网APP