Files
Atlas/internal/service/asset/sign.go
T
renjue d440fb1ae7
CI / docker (push) Has been cancelled
实现 Atlas AI 平台一期能力并完成品牌化改造。
引入用户端对话/生图与管理端 Provider 配置,统一 invoke 编排、Gateway、请求日志与模型管理;前端按设计规范拆分布局,Go module 更名为 github.com/rose_cat707/Atlas;生图长任务 SSE 推送;管理端登录防爆破;协议与服务类型联动;Replicate 模型同步修复;用户端创作台 UI 重构;管理端创作历史替代请求日志。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 22:36:49 +08:00

86 lines
1.9 KiB
Go

package asset
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"mime"
"os"
"path/filepath"
"strconv"
"strings"
"time"
"github.com/google/uuid"
)
type Signer struct {
secret string
}
func NewSigner(secret string) *Signer {
return &Signer{secret: secret}
}
func (s *Signer) Sign(fileID int64, exp int64) string {
mac := hmac.New(sha256.New, []byte(s.secret))
mac.Write([]byte(fmt.Sprintf("%d:%d", fileID, exp)))
return hex.EncodeToString(mac.Sum(nil))
}
func (s *Signer) Verify(fileID int64, exp int64, sig string) bool {
if time.Now().Unix() > exp {
return false
}
expected := s.Sign(fileID, exp)
return hmac.Equal([]byte(expected), []byte(sig))
}
func (s *Signer) SignedURL(basePath string, fileID int64, ttl time.Duration) string {
exp := time.Now().Add(ttl).Unix()
sig := s.Sign(fileID, exp)
return fmt.Sprintf("%s/user/files/%d?exp=%d&sig=%s", basePath, fileID, exp, sig)
}
func SaveUpload(dataDir, sessionID string, filename string, r io.Reader, maxBytes int64) (string, int64, string, error) {
ext := filepath.Ext(filename)
if ext == "" {
ext = ".bin"
}
id := uuid.New().String()
dir := filepath.Join(dataDir, "files", sessionID, "uploads")
if err := os.MkdirAll(dir, 0o755); err != nil {
return "", 0, "", err
}
path := filepath.Join(dir, id+ext)
f, err := os.Create(path)
if err != nil {
return "", 0, "", err
}
defer f.Close()
n, err := io.Copy(f, io.LimitReader(r, maxBytes+1))
if err != nil {
os.Remove(path)
return "", 0, "", err
}
if n > maxBytes {
os.Remove(path)
return "", 0, "", fmt.Errorf("file too large")
}
mimeType := mime.TypeByExtension(ext)
if mimeType == "" {
mimeType = "application/octet-stream"
}
return path, n, mimeType, nil
}
func ParseSignedQuery(expStr, sig string) (int64, string, error) {
exp, err := strconv.ParseInt(expStr, 10, 64)
if err != nil {
return 0, "", err
}
return exp, strings.TrimSpace(sig), nil
}