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:
2026-06-02 16:10:23 +08:00
parent 9477155bcf
commit 53f18ca6ee
25 changed files with 122 additions and 55 deletions

View File

@ -28,8 +28,8 @@
</div>
<div class="post-item-actions">
<a href="/studio/write?id={{.ID}}" class="action-btn primary">继续编辑</a>
<button class="action-btn" onclick="submitPost({{.ID}})" title="提交发布">提交</button>
<button class="action-btn danger" onclick="deletePost({{.ID}})" title="删除">删除</button>
<button class="action-btn" data-post-id="{{.ID}}" data-action="submit" title="提交发布">提交</button>
<button class="action-btn danger" data-post-id="{{.ID}}" data-action="delete" title="删除">删除</button>
</div>
</div>
{{end}}
@ -57,7 +57,7 @@
</main>
</div>
<script>
<script nonce="{{.CSPNonce}}">
function submitPost(id) {
if (!confirm('确定要提交这篇草稿进行审核吗?')) return;
@ -97,6 +97,19 @@ function deletePost(id) {
}
});
}
// 事件委托代替内联 onclick满足 CSP 无 unsafe-inline
document.addEventListener('click', function(e) {
var btn = e.target.closest('[data-action]');
if (!btn) return;
var id = btn.getAttribute('data-post-id');
var action = btn.getAttribute('data-action');
if (action === 'delete') {
deletePost(id);
} else if (action === 'submit') {
submitPost(id);
}
});
</script>
{{template "layout/footer.html" .}}