diff --git a/internal/common/helper.go b/internal/common/helper.go index 7ba88d1..3caa040 100644 --- a/internal/common/helper.go +++ b/internal/common/helper.go @@ -82,6 +82,10 @@ func BuildPageData(c *gin.Context, extra gin.H) gin.H { for k, v := range extra { data[k] = v } + // 注入 CSP nonce(由 SecurityHeaders 中间件生成) + if nonce, exists := c.Get("csp_nonce"); exists { + data["CSPNonce"] = nonce + } if username, exists := c.Get("username"); exists { data["IsLoggedIn"] = true data["Username"] = username diff --git a/internal/middleware/security.go b/internal/middleware/security.go index 7698c6e..cab764d 100644 --- a/internal/middleware/security.go +++ b/internal/middleware/security.go @@ -1,20 +1,37 @@ package middleware import ( + "crypto/rand" + "encoding/base64" + "github.com/gin-gonic/gin" ) +// generateNonce 生成 16 字节随机 nonce(base64 编码) +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 策略和模板内 - + + diff --git a/templates/MetaLab-2026/html/auth/register.html b/templates/MetaLab-2026/html/auth/register.html index e1c1350..525082a 100644 --- a/templates/MetaLab-2026/html/auth/register.html +++ b/templates/MetaLab-2026/html/auth/register.html @@ -38,7 +38,7 @@ 非共享设备推荐 - + {{else}} @@ -89,7 +89,7 @@ - - + + diff --git a/templates/MetaLab-2026/html/home/index.html b/templates/MetaLab-2026/html/home/index.html index 4bf3a6d..c04a0fb 100644 --- a/templates/MetaLab-2026/html/home/index.html +++ b/templates/MetaLab-2026/html/home/index.html @@ -64,7 +64,7 @@ {{end}} @@ -78,7 +78,7 @@ - {{template "layout/footer.html" .}} diff --git a/templates/MetaLab-2026/html/studio/write.html b/templates/MetaLab-2026/html/studio/write.html index 4f61d1f..5476148 100644 --- a/templates/MetaLab-2026/html/studio/write.html +++ b/templates/MetaLab-2026/html/studio/write.html @@ -95,8 +95,8 @@ {{template "layout/footer.html" .}} - - - + + + diff --git a/templates/MetaLab-2026/static/js/common.js b/templates/MetaLab-2026/static/js/common.js index 3dbc8dc..8283790 100644 --- a/templates/MetaLab-2026/static/js/common.js +++ b/templates/MetaLab-2026/static/js/common.js @@ -258,7 +258,8 @@ // ---- Logout ---- var logoutBtn = document.getElementById('logoutBtn'); if (logoutBtn) { - logoutBtn.addEventListener('click', function () { + logoutBtn.addEventListener('click', function (e) { + e.preventDefault(); var xhr = new XMLHttpRequest(); xhr.open('POST', '/api/auth/logout', true); xhr.onreadystatechange = function () { diff --git a/templates/admin/html/audit/index.html b/templates/admin/html/audit/index.html index e4a2cb1..88ad90b 100644 --- a/templates/admin/html/audit/index.html +++ b/templates/admin/html/audit/index.html @@ -92,12 +92,12 @@

请填写拒绝理由:

- + diff --git a/templates/admin/html/layout/footer.html b/templates/admin/html/layout/footer.html index 0888180..02684c5 100644 --- a/templates/admin/html/layout/footer.html +++ b/templates/admin/html/layout/footer.html @@ -1,9 +1,9 @@ - - + + {{if .ExtraJS}} - + {{end}} diff --git a/templates/admin/html/posts/index.html b/templates/admin/html/posts/index.html index 55b237f..45b131f 100644 --- a/templates/admin/html/posts/index.html +++ b/templates/admin/html/posts/index.html @@ -82,5 +82,5 @@ {{end}} - + {{template "admin/layout/footer.html" .}} diff --git a/templates/admin/html/users/index.html b/templates/admin/html/users/index.html index 738c28c..414155f 100644 --- a/templates/admin/html/users/index.html +++ b/templates/admin/html/users/index.html @@ -44,7 +44,7 @@
-