| @@ -13,11 +13,6 @@ import ( | |||
| cdssdk "gitlink.org.cn/cloudream/common/sdks/storage" | |||
| ) | |||
| const ( | |||
| AuthService = "jcs" | |||
| AuthRegion = "any" | |||
| ) | |||
| type PresignedService struct { | |||
| *Client | |||
| } | |||
| @@ -0,0 +1,113 @@ | |||
| package cdsapi | |||
| import ( | |||
| "bytes" | |||
| "context" | |||
| "crypto/sha256" | |||
| "encoding/hex" | |||
| "fmt" | |||
| "io" | |||
| "net/http" | |||
| "time" | |||
| v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4" | |||
| "github.com/aws/aws-sdk-go-v2/credentials" | |||
| ) | |||
| const ( | |||
| AuthService = "jcs" | |||
| AuthRegion = "any" | |||
| ) | |||
| // 对一个请求进行签名,并将签名信息添加到请求头中。 | |||
| // | |||
| // 会读取请求体计算sha256哈希值。如果hash值已知,可以使用SignWithPayloadHash方法。 | |||
| func Sign(req *http.Request, accessKey, secretKey string) error { | |||
| prod := credentials.NewStaticCredentialsProvider(accessKey, secretKey, "") | |||
| cred, err := prod.Retrieve(context.TODO()) | |||
| if err != nil { | |||
| return err | |||
| } | |||
| payloadHash := "" | |||
| if req.Body != nil { | |||
| data, err := io.ReadAll(req.Body) | |||
| if err != nil { | |||
| return err | |||
| } | |||
| req.Body.Close() | |||
| req.Body = io.NopCloser(bytes.NewReader(data)) | |||
| hasher := sha256.New() | |||
| hasher.Write(data) | |||
| payloadHash = hex.EncodeToString(hasher.Sum(nil)) | |||
| } | |||
| signer := v4.NewSigner() | |||
| err = signer.SignHTTP(context.Background(), cred, req, payloadHash, AuthService, AuthRegion, time.Now()) | |||
| if err != nil { | |||
| return err | |||
| } | |||
| return nil | |||
| } | |||
| // 对一个请求进行签名,并将签名信息添加到请求头中。 | |||
| // | |||
| // 不计算请求体的哈希,适合上传文件接口。 | |||
| func SignWithoutBody(req *http.Request, accessKey, secretKey string) error { | |||
| prod := credentials.NewStaticCredentialsProvider(accessKey, secretKey, "") | |||
| cred, err := prod.Retrieve(context.TODO()) | |||
| if err != nil { | |||
| return err | |||
| } | |||
| signer := v4.NewSigner() | |||
| err = signer.SignHTTP(context.Background(), cred, req, "", AuthService, AuthRegion, time.Now()) | |||
| if err != nil { | |||
| return err | |||
| } | |||
| return nil | |||
| } | |||
| // 对一个请求进行签名,签名时使用指定的哈希值作为请求体的哈希值。 | |||
| // | |||
| // 参数payloadHash必须为sha256哈希值的16进制字符串,全小写。 | |||
| func SignWithPayloadHash(req *http.Request, payloadHash string, accessKey, secretKey string) error { | |||
| prod := credentials.NewStaticCredentialsProvider(accessKey, secretKey, "") | |||
| cred, err := prod.Retrieve(context.TODO()) | |||
| if err != nil { | |||
| return err | |||
| } | |||
| signer := v4.NewSigner() | |||
| err = signer.SignHTTP(context.Background(), cred, req, payloadHash, AuthService, AuthRegion, time.Now()) | |||
| if err != nil { | |||
| return err | |||
| } | |||
| return nil | |||
| } | |||
| // 生成一个带签名的URL。 | |||
| // | |||
| // expiration为签名过期时间,单位为秒。 | |||
| // | |||
| // 签名时不会包含请求体的哈希值。 | |||
| func Presign(req *http.Request, accessKey, secretKey string, expiration int) (string, error) { | |||
| query := req.URL.Query() | |||
| query.Add("X-Expires", fmt.Sprintf("%v", expiration)) | |||
| req.URL.RawQuery = query.Encode() | |||
| prod := credentials.NewStaticCredentialsProvider(accessKey, secretKey, "") | |||
| cred, err := prod.Retrieve(context.TODO()) | |||
| if err != nil { | |||
| return "", err | |||
| } | |||
| signer := v4.NewSigner() | |||
| signedURL, _, err := signer.PresignHTTP(context.Background(), cred, req, "", AuthService, AuthRegion, time.Now()) | |||
| return signedURL, err | |||
| } | |||
| @@ -1,7 +1,6 @@ | |||
| package cdsapi | |||
| import ( | |||
| "context" | |||
| "crypto/sha256" | |||
| "encoding/hex" | |||
| "fmt" | |||
| @@ -11,10 +10,7 @@ import ( | |||
| ul "net/url" | |||
| "path/filepath" | |||
| "strings" | |||
| "time" | |||
| v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4" | |||
| "github.com/aws/aws-sdk-go-v2/credentials" | |||
| "github.com/google/go-querystring/query" | |||
| "gitlink.org.cn/cloudream/common/pkgs/iterator" | |||
| "gitlink.org.cn/cloudream/common/sdks" | |||
| @@ -59,14 +55,7 @@ func JSONAPI[Resp sdks.APIResponse, Req sdks.APIRequest](cfg *Config, cli *http. | |||
| } | |||
| if cfg.AccessKey != "" && cfg.SecretKey != "" { | |||
| prod := credentials.NewStaticCredentialsProvider(cfg.AccessKey, cfg.SecretKey, "") | |||
| cred, err := prod.Retrieve(context.TODO()) | |||
| if err != nil { | |||
| return re, err | |||
| } | |||
| signer := v4.NewSigner() | |||
| err = signer.SignHTTP(context.Background(), cred, httpReq, calcSha256(param.Body), AuthService, AuthRegion, time.Now()) | |||
| err = SignWithPayloadHash(httpReq, cfg.AccessKey, cfg.SecretKey, calcSha256(param.Body)) | |||
| if err != nil { | |||
| return re, err | |||
| } | |||
| @@ -90,14 +79,7 @@ func JSONAPINoData[Resp sdks.APIResponse, Req sdks.APIRequest](cfg *Config, cli | |||
| } | |||
| if cfg.AccessKey != "" && cfg.SecretKey != "" { | |||
| prod := credentials.NewStaticCredentialsProvider(cfg.AccessKey, cfg.SecretKey, "") | |||
| cred, err := prod.Retrieve(context.TODO()) | |||
| if err != nil { | |||
| return err | |||
| } | |||
| signer := v4.NewSigner() | |||
| err = signer.SignHTTP(context.Background(), cred, httpReq, calcSha256(param.Body), AuthService, AuthRegion, time.Now()) | |||
| err = SignWithPayloadHash(httpReq, cfg.AccessKey, cfg.SecretKey, calcSha256(param.Body)) | |||
| if err != nil { | |||
| return err | |||
| } | |||
| @@ -115,10 +97,12 @@ func calcSha256(body sdks.RequestBody) string { | |||
| hasher := sha256.New() | |||
| switch body := body.(type) { | |||
| case *sdks.StringBody: | |||
| return hex.EncodeToString(hasher.Sum([]byte(body.Value))) | |||
| hasher.Write([]byte(body.Value)) | |||
| return hex.EncodeToString(hasher.Sum(nil)) | |||
| case *sdks.BytesBody: | |||
| return hex.EncodeToString(hasher.Sum(body.Value)) | |||
| hasher.Write(body.Value) | |||
| return hex.EncodeToString(hasher.Sum(nil)) | |||
| default: | |||
| return "" | |||
| @@ -179,14 +163,7 @@ func PostMultiPart(cfg *Config, url string, info any, files http2.MultiPartFileI | |||
| req.Body = pr | |||
| if cfg.AccessKey != "" && cfg.SecretKey != "" { | |||
| prod := credentials.NewStaticCredentialsProvider(cfg.AccessKey, cfg.SecretKey, "") | |||
| cred, err := prod.Retrieve(context.TODO()) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| signer := v4.NewSigner() | |||
| err = signer.SignHTTP(context.Background(), cred, req, "", AuthService, AuthRegion, time.Now()) | |||
| err = SignWithoutBody(req, cfg.AccessKey, cfg.SecretKey) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||