From 9765edac9b0f8404b4509746383cd7db11b7c6b2 Mon Sep 17 00:00:00 2001 From: qing <1776177662@qq.com> Date: Thu, 30 Jul 2026 11:01:34 +0800 Subject: [PATCH] =?UTF-8?q?fix(static):=20=E5=89=8D=E7=AB=AF=E8=84=9A?= =?UTF-8?q?=E6=9C=AC=E8=AF=86=E5=88=AB=20WAF=20=E6=8B=A6=E6=88=AA=E5=93=8D?= =?UTF-8?q?=E5=BA=94=E5=B9=B6=E6=AD=A3=E7=A1=AE=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - validation.js 新增 WafTip 公共检测:403 + 响应体含 blocked by WAF 双重特征, 与 gateway 白名单拒绝的 403(JSON 错误消息)精确区分 - login/register/dnfs/view 各请求点在 JSON 解析前识别拦截,统一提示 「请求被 WAF 安全规则拦截,请检查输入内容」 - 修复 dnfs getNode 被 WAF 拦截时落入 catch 误跳登录页的问题 - 验证码图片加载识别 403 拦截,alt 提示点击重试 - __view.html 补充引入 validation.js --- static/public/__view.html | 1 + static/public/js/dnfs.js | 10 ++++++++++ static/public/js/login.js | 6 ++++++ static/public/js/register.js | 2 ++ static/public/js/validation.js | 12 ++++++++++++ static/public/js/view.js | 4 +++- 6 files changed, 34 insertions(+), 1 deletion(-) diff --git a/static/public/__view.html b/static/public/__view.html index 1690cd7..c29f08e 100644 --- a/static/public/__view.html +++ b/static/public/__view.html @@ -47,6 +47,7 @@ 蜀ICP备2024107064号-2 + diff --git a/static/public/js/dnfs.js b/static/public/js/dnfs.js index 1282fe6..b5e4e91 100644 --- a/static/public/js/dnfs.js +++ b/static/public/js/dnfs.js @@ -19,6 +19,11 @@ async function getNode(id) { }); const responseText = await res.text(); + // WAF 拦截:弹提示并中止,不能落入 catch(其会误跳登录页) + if (window.WafTip && WafTip.isBlocked(res, responseText)) { + alert(WafTip.MESSAGE); + return; + } let result; try { @@ -78,6 +83,7 @@ async function addNode(pid, title, content) { }); const responseText = await res.text(); + if (window.WafTip && WafTip.isBlocked(res, responseText)) throw new Error(WafTip.MESSAGE); let result; try { @@ -137,6 +143,7 @@ async function deleteNode(id) { }); const responseText = await res.text(); + if (window.WafTip && WafTip.isBlocked(res, responseText)) throw new Error(WafTip.MESSAGE); let result; try { @@ -188,6 +195,7 @@ async function deleteChild(id) { }); const responseText = await res.text(); + if (window.WafTip && WafTip.isBlocked(res, responseText)) throw new Error(WafTip.MESSAGE); let result; try { @@ -246,6 +254,7 @@ async function updateNode(id, pid, title, content) { }); const responseText = await res.text(); + if (window.WafTip && WafTip.isBlocked(res, responseText)) throw new Error(WafTip.MESSAGE); let result; try { @@ -301,6 +310,7 @@ async function moveNode(id, pid, title, content) { }); const responseText = await res.text(); + if (window.WafTip && WafTip.isBlocked(res, responseText)) throw new Error(WafTip.MESSAGE); let result; try { diff --git a/static/public/js/login.js b/static/public/js/login.js index fc3b7dc..1012ff6 100644 --- a/static/public/js/login.js +++ b/static/public/js/login.js @@ -22,6 +22,11 @@ async function refreshCaptcha() { captchaToken = ''; try { const res = await fetch('/captcha/image', { cache: 'no-store' }); + if (res.status === 403) { // WAF 拦截:body 非图片,提示后待用户点击重试 + captchaImg.removeAttribute('src'); + captchaImg.alt = '验证码加载被安全规则拦截,点击重试'; + return; + } if (!res.ok) throw new Error('captcha load failed'); captchaToken = res.headers.get('X-Captcha-Token') || ''; const blob = await res.blob(); @@ -126,6 +131,7 @@ form.addEventListener('submit', async function(e) { body: jsonBody }); const responseText = await res.text(); + if (window.WafTip && WafTip.isBlocked(res, responseText)) throw new Error(WafTip.MESSAGE); let result; try { result = JSON.parse(responseText); } catch { throw new Error('服务器响应格式异常'); } if (!res.ok) throw new Error(result.message || '登录失败'); diff --git a/static/public/js/register.js b/static/public/js/register.js index 86380f0..298a93c 100644 --- a/static/public/js/register.js +++ b/static/public/js/register.js @@ -143,6 +143,7 @@ getCodeButton.addEventListener('click', async function () { }); httpStatus = res.status; const responseText = await res.text(); + if (window.WafTip && WafTip.isBlocked(res, responseText)) throw new Error(WafTip.MESSAGE); let result; try { result = JSON.parse(responseText); } catch { throw new Error('服务器响应格式异常'); } if (!res.ok || !result.success) throw new Error(result.message || '验证码发送失败'); @@ -190,6 +191,7 @@ form.addEventListener('submit', async function (e) { }); const responseText = await res.text(); + if (window.WafTip && WafTip.isBlocked(res, responseText)) throw new Error(WafTip.MESSAGE); let result; try { diff --git a/static/public/js/validation.js b/static/public/js/validation.js index 03ecc5f..1779c61 100644 --- a/static/public/js/validation.js +++ b/static/public/js/validation.js @@ -68,3 +68,15 @@ window.FormValidators = { username, password, email }; }()); + +/* WAF 拦截识别:waf 命中规则时返回 403 + 纯文本 "blocked by WAF" + * (见 waf/internal/proxy/proxy.go block());gateway 的 403(Target-Url + * 白名单拒绝)body 为 JSON 错误消息,不含此特征,不会误判。 */ +window.WafTip = { + MESSAGE: '请求被 WAF 安全规则拦截,请检查输入内容', + isBlocked(res, responseText) { + return res.status === 403 + && typeof responseText === 'string' + && responseText.indexOf('blocked by WAF') !== -1; + } +}; diff --git a/static/public/js/view.js b/static/public/js/view.js index f42723e..0c06be8 100644 --- a/static/public/js/view.js +++ b/static/public/js/view.js @@ -138,7 +138,9 @@ async function loadData() { try { const url = `/api/filelist?path=${encodeURIComponent(currentPath)}`; const res = await fetch(url); - const data = await res.json(); + const responseText = await res.text(); + if (window.WafTip && WafTip.isBlocked(res, responseText)) throw new Error(WafTip.MESSAGE); + const data = JSON.parse(responseText); if (data.success) { items = data.items || []; render();