From 940393c1505cb61d58fa66c7391c102a92ca400d Mon Sep 17 00:00:00 2001 From: nyne Date: Thu, 27 Nov 2025 20:03:17 +0800 Subject: [PATCH] feat: implement download token generation for secure file access --- .env.example | 3 +++ server/api/file.go | 13 ++++++++++++- server/utils/jwt.go | 24 +++++++++++++++++++++++- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index d8e9497..3812d87 100644 --- a/.env.example +++ b/.env.example @@ -30,3 +30,6 @@ BACKUP_SCHEDULE=0 2 * * * # Retention policy (days) BACKUP_RETENTION_DAYS=30 + +# Download Configuration +DOWNLOAD_SECRET_KEY=your_download_secret_key_here \ No newline at end of file diff --git a/server/api/file.go b/server/api/file.go index 4624924..49c4b8b 100644 --- a/server/api/file.go +++ b/server/api/file.go @@ -225,7 +225,18 @@ func downloadFile(c fiber.Ctx) error { return err } if strings.HasPrefix(s, "http") { - return c.Redirect().Status(fiber.StatusFound).To(s) + uri, err := url.Parse(s) + if err != nil { + return err + } + token, err := utils.GenerateDownloadToken(s) + if err != nil { + return err + } + q := uri.Query() + q.Set("token", token) + uri.RawQuery = q.Encode() + return c.Redirect().Status(fiber.StatusFound).To(uri.String()) } data := map[string]string{ "path": s, diff --git a/server/utils/jwt.go b/server/utils/jwt.go index 06d12a9..7f061bb 100644 --- a/server/utils/jwt.go +++ b/server/utils/jwt.go @@ -3,9 +3,10 @@ package utils import ( "crypto/rand" "errors" - "github.com/golang-jwt/jwt/v5" "os" "time" + + "github.com/golang-jwt/jwt/v5" ) var ( @@ -93,3 +94,24 @@ func ParseTemporaryToken(token string) (string, error) { } return "", errors.New("invalid token") } + +func GenerateDownloadToken(fileKey string) (string, error) { + secretKeyStr := os.Getenv("DOWNLOAD_SECRET_KEY") + var secretKey []byte + if secretKeyStr == "" { + secretKey = key + } else { + secretKey = []byte(secretKeyStr) + } + + t := jwt.NewWithClaims(jwt.SigningMethodHS256, + jwt.MapClaims{ + "fileKey": fileKey, + "exp": time.Now().Add(1 * time.Hour).Unix(), + }) + s, err := t.SignedString(secretKey) + if err != nil { + return "", err + } + return s, nil +}