- 新增 SecureMedia 组件以支持安全媒体播放 - 更新导航栏和侧边栏结构,将"processed"重命名为"enhance" - 在主题配置中添加 PDF.js 相关设置 - 更新 .gitignore 文件以排除 pdfjs 相关目录
80 lines
1.6 KiB
Go
80 lines
1.6 KiB
Go
package handlers
|
||
|
||
import (
|
||
"crypto/md5"
|
||
"encoding/hex"
|
||
"fmt"
|
||
"net/http"
|
||
"net/url"
|
||
"os"
|
||
"strings"
|
||
"time"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
)
|
||
|
||
type SecureUrlRequest struct {
|
||
URL string `json:"url"`
|
||
}
|
||
|
||
// urlEncode 对URL路径进行编码,保持斜杠不变
|
||
func urlEncode(s string) string {
|
||
return strings.ReplaceAll(url.QueryEscape(s), "%2F", "/")
|
||
}
|
||
|
||
// toHex16 将时间戳转换为16进制小写形式
|
||
func toHex16(t int64) string {
|
||
return fmt.Sprintf("%x", t)
|
||
}
|
||
|
||
func GenerateSecureURL(c *gin.Context) {
|
||
var req SecureUrlRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的请求"})
|
||
return
|
||
}
|
||
|
||
// 从环境变量获取防盗链密钥
|
||
secretKey := os.Getenv("QINIU_ANTILEECH_KEY")
|
||
if secretKey == "" {
|
||
c.JSON(http.StatusInternalServerError, gin.H{"error": "未配置防盗链密钥"})
|
||
return
|
||
}
|
||
|
||
// 设置链接有效期为5分钟
|
||
deadline := time.Now().Add(5 * time.Minute).Unix()
|
||
deadlineHex := toHex16(deadline)
|
||
|
||
// 解析URL
|
||
parsedURL, err := url.Parse(req.URL)
|
||
if err != nil {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的URL"})
|
||
return
|
||
}
|
||
|
||
// 获取并编码路径部分
|
||
urlPath := parsedURL.Path
|
||
encodedPath := urlEncode(urlPath)
|
||
|
||
// 构建签名字符串
|
||
signStr := secretKey + encodedPath + deadlineHex
|
||
|
||
// 计算MD5签名
|
||
hash := md5.New()
|
||
hash.Write([]byte(signStr))
|
||
sign := hex.EncodeToString(hash.Sum(nil))
|
||
|
||
// 构建查询参数
|
||
query := parsedURL.Query()
|
||
query.Set("sign", sign)
|
||
query.Set("t", deadlineHex)
|
||
|
||
// 重建URL
|
||
parsedURL.RawQuery = query.Encode()
|
||
secureUrl := parsedURL.String()
|
||
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"secureUrl": secureUrl,
|
||
})
|
||
}
|