From 35d322443b1ba8b3fa9c2ed7421111808d86b6de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=83=E7=9F=B3?= Date: Sat, 11 Oct 2025 04:14:13 -0700 Subject: [PATCH] feat(driver): Add URL signing support (#9347) Introduces the ability to sign generated URLs for enhanced security and access control. This feature is activated by configuring a `PrivateKey`, `UID`, and `ValidDuration` in the driver settings. If a private key is provided, the driver will sign the output URLs, making them time-limited based on the `ValidDuration`. The `ValidDuration` defaults to 30 minutes if not specified. The core signing logic is encapsulated in the new `sign.go` file. The `driver.go` file integrates this signing process before returning the final URL. --- drivers/123_open/driver.go | 19 ++++++++++++++++++- drivers/123_open/meta.go | 7 +++++-- drivers/123_open/sign.go | 27 +++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 drivers/123_open/sign.go diff --git a/drivers/123_open/driver.go b/drivers/123_open/driver.go index 39ed146e..ace86bb9 100644 --- a/drivers/123_open/driver.go +++ b/drivers/123_open/driver.go @@ -11,6 +11,7 @@ import ( "github.com/go-resty/resty/v2" "net/http" "strconv" + "time" ) type Open123 struct { @@ -89,8 +90,24 @@ func (d *Open123) Link(ctx context.Context, file model.Obj, args model.LinkArgs) return nil, fmt.Errorf("get link failed: %s", result.Message) } + linkURL := result.Data.URL + if d.PrivateKey != "" { + if d.UID == 0 { + return nil, fmt.Errorf("uid is required when private key is set") + } + duration := time.Duration(d.ValidDuration) + if duration <= 0 { + duration = 30 + } + signedURL, err := SignURL(linkURL, d.PrivateKey, d.UID, duration*time.Minute) + if err != nil { + return nil, err + } + linkURL = signedURL + } + return &model.Link{ - URL: result.Data.URL, + URL: linkURL, }, nil } diff --git a/drivers/123_open/meta.go b/drivers/123_open/meta.go index d99bb75b..d0b117aa 100644 --- a/drivers/123_open/meta.go +++ b/drivers/123_open/meta.go @@ -8,8 +8,11 @@ import ( type Addition struct { driver.RootID - ClientID string `json:"client_id" required:"true" label:"Client ID"` - ClientSecret string `json:"client_secret" required:"true" label:"Client Secret"` + ClientID string `json:"client_id" required:"true" label:"Client ID"` + ClientSecret string `json:"client_secret" required:"true" label:"Client Secret"` + PrivateKey string `json:"private_key"` + UID uint64 `json:"uid" type:"number"` + ValidDuration int64 `json:"valid_duration" type:"number" default:"30" help:"minutes"` } var config = driver.Config{ diff --git a/drivers/123_open/sign.go b/drivers/123_open/sign.go new file mode 100644 index 00000000..549d7ad8 --- /dev/null +++ b/drivers/123_open/sign.go @@ -0,0 +1,27 @@ +package _123Open + +import ( + "crypto/md5" + "fmt" + "math/rand" + "net/url" + "time" +) + +func SignURL(originURL, privateKey string, uid uint64, validDuration time.Duration) (string, error) { + if privateKey == "" { + return originURL, nil + } + parsed, err := url.Parse(originURL) + if err != nil { + return "", err + } + ts := time.Now().Add(validDuration).Unix() + randInt := rand.Int() + signature := fmt.Sprintf("%d-%d-%d-%x", ts, randInt, uid, md5.Sum([]byte(fmt.Sprintf("%s-%d-%d-%d-%s", + parsed.Path, ts, randInt, uid, privateKey)))) + query := parsed.Query() + query.Add("auth_key", signature) + parsed.RawQuery = query.Encode() + return parsed.String(), nil +}