Browse Source

拆分签名逻辑

feature_gxh
Sydonian 8 months ago
parent
commit
794e9708ad
3 changed files with 120 additions and 35 deletions
  1. +0
    -5
      sdks/storage/cdsapi/presigned.go
  2. +113
    -0
      sdks/storage/cdsapi/signer.go
  3. +7
    -30
      sdks/storage/cdsapi/utils.go

+ 0
- 5
sdks/storage/cdsapi/presigned.go View File

@@ -13,11 +13,6 @@ import (
cdssdk "gitlink.org.cn/cloudream/common/sdks/storage"
)

const (
AuthService = "jcs"
AuthRegion = "any"
)

type PresignedService struct {
*Client
}


+ 113
- 0
sdks/storage/cdsapi/signer.go View File

@@ -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
}

+ 7
- 30
sdks/storage/cdsapi/utils.go View File

@@ -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
}


Loading…
Cancel
Save