- SecurityHeaders 中间件生成随机 nonce,注入 context - BuildPageData/BuildAdminPageData 将 CSPNonce 传递给模板 - 所有 19 个模板文件 <script> 标签添加 nonce 属性 - 移除所有内联事件处理(onclick/onerror),改用事件监听 - 移除所有 javascript:void(0) 链接,改用 # 号 + preventDefault - utils.js 添加全局 avatar 图片加载失败回退处理 - common.js 登出按钮添加 preventDefault - audit.js 关闭弹窗按钮改用事件监听
25 lines
1007 B
JavaScript
25 lines
1007 B
JavaScript
/* ============================================================
|
||
MetaLab 共享工具函数 — 前后台公用,消除 DRY 重复
|
||
============================================================ */
|
||
'use strict';
|
||
|
||
/**
|
||
* 从 <meta name="csrf-token"> 读取 CSRF 令牌
|
||
* 由服务端 CSRF 中间件注入到页面模板的 <meta> 标签中
|
||
* @returns {string} CSRF 令牌,未找到时返回空字符串
|
||
*/
|
||
function getCSRFToken() {
|
||
var meta = document.querySelector('meta[name="csrf-token"]');
|
||
return meta ? meta.getAttribute('content') : '';
|
||
}
|
||
|
||
// 全局头像图片加载失败回退(替代 onerror 内联事件,满足 CSP 无 unsafe-inline)
|
||
document.addEventListener('error', function(e) {
|
||
var img = e.target;
|
||
if (img && img.tagName === 'IMG' && (img.classList.contains('nav-avatar') || img.classList.contains('user-avatar-img'))) {
|
||
img.style.display = 'none';
|
||
var next = img.nextElementSibling;
|
||
if (next) next.style.display = 'flex';
|
||
}
|
||
}, true);
|