HTML表单pattern属性仅支持全字符串匹配的白名单校验,无法直接实现黑名单式校验;如/[{}]/不能禁止输入含方括号或花括号的字符串。

HTML表单里不能直接用正则校验黑名单
HTML的 pattern 属性只支持「白名单式」匹配,也就是必须整个输入值**完全匹配**正则才通过。它没有“禁止出现某字符”的原生能力——你写 /[{}]/ 并不会让含 的输入报错,反而会让「只有 <code> 或 <code>>」这种极短输入意外通过。
用 oninput + test() 实时拦截黑名单字符
真正可控的方式是监听输入事件,用 JavaScript 主动检测并阻止非法字符。关键点在于:不是等提交再校验,而是在按键按下瞬间就过滤掉黑名单符号。
常见错误现象:onchange 太晚(失焦才触发),onkeypress 拦不住粘贴、拖入、IME 输入;oninput 覆盖最全。
- 黑名单正则要加
g标志,确保检测所有匹配项,例如/[&'"`{}[]();\/ --]/g - 用
event.target.value.replace(正则, '')直接剔除非法字符,比test()后弹提示更防绕过 - 必须同时监听
input和paste事件,粘贴内容可能绕过键盘拦截
<input type="text" id="safeInput">
<script>
const input = document.getElementById('safeInput');
const blacklist = /[<>&'"`{}[]();\/ --]/g;
input.addEventListener('input', () => {
input.value = input.value.replace(blacklist, '');
});
input.addEventListener('paste', (e) => {
setTimeout(() => input.value = input.value.replace(blacklist, ''), 0);
});
</script>
pattern 只能曲线救国:用否定字符组做白名单
如果非要用 HTML 原生校验,唯一办法是反向定义「允许什么」,比如只允许字母、数字、下划线、短横线:pattern="[a-zA-Z0-9_-]*"。这本质是白名单,不是黑名单。
立即学习“前端免费学习笔记(深入)”;
容易踩的坑:
- 中文、空格、emoji 等常用字符默认被排除,业务上往往不可接受
-
pattern不校验空字符串,需额外加required - 正则开头结尾不加
^和$—— 浏览器会自动加上,写反而报错
服务端才是最终防线,前端只是体验层
任何前端校验都可被禁用或绕过。用户删掉 oninput 监听、用 curl 提交、甚至直接改 DOM,都能把 <script></script> 送进来。所以:
- 后端必须对所有输入字段重新执行相同黑名单过滤(不能只信
pattern) - 涉及渲染到 HTML 的内容,必须用安全函数转义,如 Node.js 的
he.escape(),Python 的html.escape() - 数据库写入前也建议过滤控制字符(
