应主动扫描而非依赖事件委托识别未防盗链图片,通过检查img的referrerpolicy属性、跨域src及mutationobserver动态监控实现启发式标记。
在多图文混合排版页面中,要利用事件委托识别并过滤出所有未做安全防盗链的 img 元素,关键不是监听用户点击,而是主动扫描、比对 referrer 策略与实际加载行为。事件委托在此场景下不直接适用——因为防盗链失效发生在资源加载阶段(非 dom 交互),但你可以用它辅助后续操作(比如统一打标、上报或动态拦截)。以下是实用路径:
一、明确“未做防盗链”的判定依据
真正可检测的信号是:图片请求未携带有效的 Referer 或 Referrer-Policy 头,且来源域不在白名单内。但注意:浏览器不向 JS 暴露网络请求头,所以不能靠 document.querySelectorAll('img') 直接读取 header。可行替代方案有:
- 检查
<img>的referrerpolicy属性是否为"no-referrer"或"origin-when-cross-origin"(较安全),若缺失或为"unsafe-url",属于高风险配置; - 检查图片
src是否为相对路径或同源地址(这类通常无防盗链压力);跨域外链(如https://cdn.example.com/xxx.jpg)才需重点筛查; - 观察图片是否能正常加载(
onload)但控制台报 CORS 或 Referrer 被拒警告(需人工或 DevTools 配合,不可编程自动捕获); - 服务端日志才是最终依据,前端仅能做启发式标记。
二、用事件委托辅助“动态发现”和“批量处理”
虽然防盗链本身无法在 JS 中实时验证,但你可以把事件委托用在用户触发行为后的响应环节,例如点击“检查防盗链”按钮、切换画廊分页、或滚动加载新图后:
- 给图片容器(如
#gallery)绑定click或scroll事件,用e.target.closest('img')捕获目标; - 对匹配到的
img,检查其src协议+域名是否与当前页面 origin 不同,且referrerpolicy属性未设置或值宽松; - 符合条件的,添加自定义类(如
data-no-anti-leech)或记录到数组,供后续统一处理(替换占位图、插入警告角标等)。
三、实际可落地的 JS 片段(带防误判)
以下代码在页面加载完成后执行一次扫描,并支持后续动态新增图片(通过 MutationObserver + 事件委托兜底):
function findUnprotectedImages() {
const imgs = Array.from(document.querySelectorAll('img'));
return imgs.filter(img => {
const src = img.src || img.getAttribute('src');
if (!src) return false;
try {
const url = new URL(src);
// 仅检查跨域图
if (url.origin === location.origin) return false;
// referrerpolicy 缺失 或 明确允许发送全量 referer
const policy = img.referrerPolicy || img.getAttribute('referrerpolicy') || '';
return !policy || policy === 'unsafe-url';
} catch {
return false;
}
});
}
// 初始扫描
const unprotected = findUnprotectedImages();
console.table(unprotected.map(img => ({
src: img.src.slice(0, 60) + '...',
policy: img.referrerPolicy
})));
// 动态监听新插入的 img(例如 CMS 插件、富文本粘贴)
const observer = new MutationObserver(mutations => {
mutations.forEach(m => {
m.addedNodes.forEach(node => {
if (node.nodeType === 1) {
node.querySelectorAll?.('img').forEach(img => {
if (!img.hasAttribute('data-checked')) {
img.setAttribute('data-checked', '1');
if (findUnprotectedImages().includes(img)) {
img.classList.add('unprotected-img');
}
}
});
}
});
});
});
observer.observe(document.body, { childList: true, subtree: true });
四、注意事项与边界情况
- CDN 图片即使没设
referrerpolicy,也可能通过服务端规则(如 Nginx 的valid_referers)实现防盗链,前端无法感知; - 使用
loading="lazy"的图片可能尚未解析 src,需结合IntersectionObserver延迟检测; - 不要依赖
document.referrer判断——它是页面级的,不是单张图的请求上下文; - 真正加固应由后端配合:返回 403 时前端可监听
img.onerror,但仅作 fallback 提示,不能替代策略配置。











