fix: CSP 策略移除 unsafe-inline,改用 nonce 机制
- SecurityHeaders 中间件生成随机 nonce,注入 context - BuildPageData/BuildAdminPageData 将 CSPNonce 传递给模板 - 所有 19 个模板文件 <script> 标签添加 nonce 属性 - 移除所有内联事件处理(onclick/onerror),改用事件监听 - 移除所有 javascript:void(0) 链接,改用 # 号 + preventDefault - utils.js 添加全局 avatar 图片加载失败回退处理 - common.js 登出按钮添加 preventDefault - audit.js 关闭弹窗按钮改用事件监听
This commit is contained in:
@ -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
|
||||
|
||||
@ -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 策略和模板内 <script>/<style> 标签
|
||||
nonce := generateNonce()
|
||||
c.Set("csp_nonce", nonce)
|
||||
|
||||
// Content-Security-Policy
|
||||
// script-src/style-src: 本站 + inline(highlight.js 主题已本地化在 static/vditor/ 下)
|
||||
// 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'; "+
|
||||
"style-src 'self' 'unsafe-inline'; "+
|
||||
"script-src 'self' 'nonce-"+nonce+"'; "+
|
||||
"style-src 'self' 'nonce-"+nonce+"'; "+
|
||||
"img-src 'self' data: blob:; "+
|
||||
"connect-src 'self'")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user