必须用 new URL() 做基础校验并 trim() 输入,再限制协议(仅 http:/https:)、域名(如 .mycompany.com 白名单),前端用 setCustomValidity() 提示,后端须二次验证并标准化存储。

网址输入控件要过滤不合法 URL,不能只靠前端 placeholder 或正则简单匹配,得从前端校验、协议控制、域名约束到后端兜底层层设防。核心是:用 new URL() 做基础格式守门,再叠加业务规则(如仅允许 https、限定域名),同时严防 javascript:、data: 等伪协议。
用 new URL() 主动解析并捕获格式错误
这是目前最可靠的基础校验方式,比正则或字符串匹配强得多:
- 必须先对用户输入 trim(),否则带空格的 " https://a.com " 会直接抛
TypeError -
new URL(s)能识别协议缺失(如 a.com)、主机名非法(如 user@domain)、中文域名未编码、尾部多余字符等问题 - 校验通过后可安全读取
.protocol(带冒号,如"https:")、.hostname、.pathname等属性做后续判断
限制协议和域名,拒绝高危模式
格式合法 ≠ 安全可用,需按业务要求进一步过滤:
- 只允许
https:和http:,拒绝javascript:、vbscript:、data:、file:等伪协议 - 内部系统可强制白名单域名,例如只接受以
".mycompany.com"结尾的 hostname - 若允许相对路径(如
/login、./assets/img.png),需单独用url.startsWith('/') || url.startsWith('./')分支处理,不走new URL()
前端用 setCustomValidity() 统一控制提示
避免浏览器默认英文报错,也防止绕过 required 校验:
立即学习“前端免费学习笔记(深入)”;
- 监听
input或blur事件,在 JS 中调用input.checkValidity() - 校验失败时调用
input.setCustomValidity("请输入有效的 HTTPS 链接"),成功时调用input.setCustomValidity("") - 注意:必须配合
required属性或显式设置input.validity.valid = false才能触发提示
后端绝不信任前端,必须二次验证
前端一切控制都可被绕过,后端才是最后一道防线:
- PHP 推荐组合使用:
filter_var($url, FILTER_VALIDATE_URL)+ 手动检查parse_url($url, PHP_URL_SCHEME)是否在白名单中 - 拒绝任何含
javascript:、onerror=、onclick=的原始字符串,哪怕它能通过FILTER_VALIDATE_URL - 存储前建议对 URL 做标准化处理(如统一小写、补全协议、移除末尾斜杠),便于后续比对和缓存



















