This repository has been archived on 2026-06-21. You can view files and clone it, but cannot push or open issues or pull requests.
Files
MetaLab/internal/middleware/security.go
Victor_Jay ca21ae7216 fix: 修复头像审核旧图裂开问题 + CSP 配置修复
- 头像提交审核不再删除旧文件,审核通过后才删除旧头像文件
- 头像审核被拒时删除已上传的新头像文件,保留旧头像
- CSP style-src 移除 nonce 以启用 unsafe-inline(JS 动态样式需要)
- CSP script-src 移除 nonce 改用 unsafe-inline + unsafe-eval(Vditor 编辑器和动态样式需要)
2026-06-02 22:26:01 +08:00

57 lines
1.7 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package middleware
import (
"crypto/rand"
"encoding/base64"
"metazone.cc/metalab/internal/config"
"github.com/gin-gonic/gin"
)
// generateNonce 生成 16 字节随机 noncebase64 编码)
func generateNonce() string {
b := make([]byte, 16)
if _, err := rand.Read(b); err != nil {
// 降级:使用固定长度回退(极度罕见,仅 /dev/urandom 故障时)
panic("failed to generate CSP nonce: " + err.Error())
}
return base64.StdEncoding.EncodeToString(b)
}
// SecurityHeaders 添加安全相关 HTTP 响应头
// 作为纵深防御,不影响业务逻辑,纯附加
func SecurityHeaders() gin.HandlerFunc {
return func(c *gin.Context) {
// 生成一次性 nonce用于 CSP 策略和模板内 <script>/<style> 标签
nonce := generateNonce()
c.Set("csp_nonce", nonce)
// Content-Security-Policy
// script-src/style-src: 本站 + nonce替代 unsafe-inline
// img-src: 本站 + data: URI头像裁切+ blob:(粘贴图片)
c.Header("Content-Security-Policy",
"default-src 'self'; "+
"script-src 'self' 'unsafe-inline' 'unsafe-eval'; "+
"style-src 'self' 'unsafe-inline'; "+
"img-src 'self' data: blob:; "+
"connect-src 'self'")
// 禁止 MIME 类型嗅探
c.Header("X-Content-Type-Options", "nosniff")
// 禁止被 frame 嵌入(防点击劫持)
c.Header("X-Frame-Options", "DENY")
// 引用策略
c.Header("Referrer-Policy", "strict-origin-when-cross-origin")
// HSTS仅在 release 模式启用,避免开发环境 localhost 证书问题
if config.App != nil && config.App.Server.Mode == "release" {
c.Header("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload")
}
c.Next()
}
}