将 S3 协议与 Supabase 存储一起使用时出现 Golang AWS SDK v2 SignatureDoesNotMatch 错误

问题描述 投票:0回答:1

背景

我正在尝试使用 Golang 中的 S3 协议与 Supabase 的存储进行交互。我按照 Supabase 在 JavaScript 中提供的示例并将其翻译成 Go,但我一直遇到 SignatureDoesNotMatch 错误。

我的设置

我创建了一个名为 uploads 的存储桶。我在我的 supabase 项目设置中创建了一个新的访问密钥(访问密钥和秘密密钥)。我将它们放入名为

AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
.

的 .env 文件中

我的代码

这是我编写的用于使用 s3 协议与 supabase 存储交互的代码。

package providers

import (
    "context"
    "io"
    "log"

    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/s3"
)

type S3ProviderImpl interface {
    Upload(fileName string, data io.ReadCloser, bucket string) (string, error)
}

type StorageProvider struct {
    s3cl *s3.Client
}

func NewStorageProvider() *StorageProvider {
    endpoint := "https://sldogsqddfisyaxbeujt.supabase.co/storage/v1/s3"

    cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion("ap-southeast-1"))
    if err != nil {
        log.Printf("error: %v", err)
        return nil
    }

    client := s3.NewFromConfig(cfg, func(o *s3.Options) {
        o.BaseEndpoint = aws.String(endpoint)
        o.UsePathStyle = true
    })

    return &StorageProvider{
        s3cl: client,
    }
}

// This is a test function
func (provider *StorageProvider) List() {
    res, err := provider.s3cl.ListBuckets(context.TODO(), &s3.ListBucketsInput{})
    if err != nil {
        log.Println(err)
    }
    for _, object := range res.Buckets {
        log.Printf("key=%s ", aws.ToString(object.Name))
    }

}

main.go
文件中,我创建了一个新的
StorageProvider
并调用了
List
函数。

package main

import (
    "amelia/internal/providers"
    "log"

    "github.com/joho/godotenv"
    _ "github.com/lib/pq"
    "github.com/rs/zerolog"
)

func startup() {
    log.Println("Loading .env")
    err := godotenv.Load(".env")
    if err != nil {
        log.Panic(err)
    }
}

func main() {
    startup()
    storage := providers.NewStorageProvider()
    storage.List()
}

我的参考

由于supabase仅提供有关如何仅在javascript中使用s3协议的说明,我想将其翻译为go。在他们的例子中他们写了这个。

import { S3Client } from '@aws-sdk/client-s3';

const client = new S3Client({
  forcePathStyle: true,
  region: 'project_region',
  endpoint: 'https://project_ref.supabase.co/storage/v1/s3',
  credentials: {
    accessKeyId: 'your_access_key_id',
    accessSecretKey: 'your_secret_access_key',
  }
})

我尝试过的事情

我阅读了适用于 go 的 AWS SDK v2 并尝试做同样的事情。但我总是遇到这个错误。

024/05/21 18:27:53 operation error S3: ListBuckets, https response error StatusCode: 403, RequestID: , HostID: , api error SignatureDoesNotMatch: The request signature we calculated does not match the signature you provided. Check your key and signing method.

所以我尝试使用 aws cli 与其进行交互。它起作用了。我已将所有内容设置为相同,包括访问密钥和密钥、位置和端点。

PS C:\Users\josti> aws s3 ls uploads --endpoint=https://sldogsqddfisyaxbeujt.supabase.co/storage/v1/s3
2024-05-20 16:49:24       8269 abc.jpg

我尝试遵循其他人的建议,例如在存储桶名称末尾添加

/
,验证我的密钥,在文件名之前添加
./
/
,但似乎没有任何效果。

我的环境

操作系统:Windows 11 24h2
去:1.22
AWS 开发工具包版本:

github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.3 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.7 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.7 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.7 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.9 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.9 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.7 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.20.8 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.2 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.28.9 

编辑: 包含

main.go
文件以供澄清。

amazon-web-services go amazon-s3 supabase
1个回答
0
投票

对于像我一样在这方面花费太多时间的人;我仅使用 v4 请求签名者 (github.com/aws/aws-sdk-go-v2/aws/signer/v4) 并自己调用 s3 就取得了成功,如下所示:

req, err := http.NewRequest("GET", "{supabaseurl}/{bucketname}/{key}", nil)

if err != nil {
    return "", err
}

creds := aws.Credentials{
    AccessKeyID:    "supabase-s3-access-key",
    SecretAccessKey: "supabase-s3-secret-key",
}

err = signer.SignHTTP(context.Background(),
    creds,
    req,
    // empty string hash, no payload
    "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
    "s3",
    "region",
    time.Now(),
)

if err != nil {
    return "", err
}

client := &http.Client{}

resp, err := client.Do(req)
if err != nil {
    return "", err
}
defer resp.Body.Close()
© www.soinside.com 2019 - 2024. All rights reserved.