From 4481569d7e741b84e504d9411ec16365d49b458d Mon Sep 17 00:00:00 2001 From: orenzhang Date: Mon, 2 Dec 2024 17:49:27 +0800 Subject: [PATCH] =?UTF-8?q?feat(cos):=20=E6=94=AF=E6=8C=81=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E8=85=BE=E8=AE=AF=E4=BA=91CDN=E9=89=B4=E6=9D=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/filesystem/driver/cos/handler.go | 48 +++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/pkg/filesystem/driver/cos/handler.go b/pkg/filesystem/driver/cos/handler.go index 50b500c5..63e5c4a4 100644 --- a/pkg/filesystem/driver/cos/handler.go +++ b/pkg/filesystem/driver/cos/handler.go @@ -3,14 +3,18 @@ package cos import ( "context" "crypto/hmac" + "crypto/md5" "crypto/sha1" "encoding/base64" + "encoding/hex" "encoding/json" "errors" "fmt" + "github.com/google/uuid" "io" "net/http" "net/url" + "os" "path" "path/filepath" "strings" @@ -311,7 +315,7 @@ func (handler Driver) signSourceURL(ctx context.Context, path string, ttl int64, file.RawQuery = optionQuery.Encode() sourceURL := cdnURL.ResolveReference(file) - return sourceURL.String(), nil + return signCDNURL(sourceURL.String()) } presignedURL, err := handler.Client.Object.GetPresignedURL(ctx, http.MethodGet, path, @@ -327,6 +331,48 @@ func (handler Driver) signSourceURL(ctx context.Context, path string, ttl int64, return presignedURL.String(), nil } +// 支持腾讯云 CDN 的 Type A 鉴权 +func signCDNURL(rawUrl string) (string, error) { + // 初始化参数 + cdnHostname := os.Getenv("TCLOUD_CDN_HOSTNAME") + cdnSignKey := os.Getenv("TCLOUD_CDN_SIGN_KEY") + cdnSignKeyURLParam := os.Getenv("TCLOUD_CDN_KEY_URL_PARAM") + if cdnHostname == "" || cdnSignKey == "" || cdnSignKeyURLParam == "" { + return rawUrl, nil + } + + // 解析 URL + parsedUrl, err := url.Parse(rawUrl) + if err != nil { + return "", err + } + + // 判断是否需要签名 + if parsedUrl.Hostname() != cdnHostname { + return rawUrl, nil + } + + // 签名 + timestamp := time.Now().Unix() + random, err := uuid.NewRandom() + if err != nil { + return "", err + } + nonce := strings.Replace(random.String(), "-", "", 4) + uid := "0" + signatureString := fmt.Sprintf("%s-%d-%s-%s-%s", parsedUrl.Path, timestamp, nonce, uid, cdnSignKey) + hash := md5.Sum([]byte(signatureString)) + signature := hex.EncodeToString(hash[:]) + + // 添加签名到URL参数 + urlQuery := parsedUrl.Query() + urlQuery.Set(cdnSignKeyURLParam, fmt.Sprintf("%d-%s-%s-%s", timestamp, nonce, uid, signature)) + parsedUrl.RawQuery = urlQuery.Encode() + + // 返回URL + return parsedUrl.String(), nil +} + // Token 获取上传策略和认证Token func (handler Driver) Token(ctx context.Context, ttl int64, uploadSession *serializer.UploadSession, file fsctx.FileHeader) (*serializer.UploadCredential, error) { // 生成回调地址