前端安全拦截仅优化体验,不能替代后端校验;accept 属性仅提示文件类型,无法阻止非法文件上传;js 校验 file.name 和 file.size 易被绕过,必须在后端重做魔数检测、白名单过滤、重命名及存储隔离。

前端安全拦截本身不提供真正安全,只做体验优化和初步过滤;所有校验必须在后端重做,否则等于没设防。
accept 属性只能提示,不能阻止非法文件选择
设置 accept=".pdf,.docx" 会让文件选择对话框默认只显示匹配类型,但用户点击“全部文件”就能选任意后缀。浏览器不会拒绝你传 evil.php,只要它带个 .pdf 后缀就放行。
常见错误现象:input.files[0] 里确实拿到了一个名为 shell.php 的文件,但 accept 没起作用——这完全正常,不是 bug。
使用建议:
- 仍应设置
accept,提升 UX,减少误操作 - 不要把它当校验依据,更别用它决定按钮是否启用
- 对图片类上传,可加
accept="image/*"配合后续 JS 校验
JavaScript 校验 file.name 和 file.size 是必要但脆弱的步骤
file.name 可取扩展名(如 file.name.split('.').pop().toLowerCase()),file.size 可判断是否超限(如 file.size > 10 * 1024 * 1024)。但这两种检查都极易绕过:改后缀、拖拽上传时 file.type 常为空、抓包直接发恶意 payload。
容易踩的坑:
- 只看
file.type—— 它由浏览器根据扩展名或魔数推测,不可信,且拖拽场景下常为"" - 用正则匹配
file.name却忽略大小写,导致.PHP漏过 - 限制了大小却没在后端同步配置(如 Node.js 的
multer或 Nginx 的client_max_body_size),结果前端拦住了,后端直接 413
前端能做的真正有效动作只有禁用提交 + 清晰反馈
JS 校验的意义不是“挡住攻击”,而是“让用户立刻知道哪里不对”。一旦发现扩展名不符或超大,就该禁用提交按钮、高亮输入框、给出明确文字提示(比如“仅支持 PNG/JPG,当前是 .exe”)。
实操建议:
- 监听
input[type="file"]的change事件,而非表单submit—— 提前拦截,避免无效请求打到后端 - 校验失败时,调用
event.preventDefault()并清空input.files(部分浏览器需手动赋值input.value = "") - 不要隐藏文件 input,也不要用 label 模拟上传按钮后丢失原生
files对象引用 - 若用拖拽上传,记得同时处理
drop和change,且两者都要走同一套校验逻辑
最常被忽略的一点:前端校验代码本身可能被禁用(浏览器关 JS)、被跳过(直接 POST 请求)、或被覆盖(篡改 DOM)。它存在的唯一合理理由,是让合法用户少点几次“上传失败”,而不是让你觉得“加了这个就安全了”。真正的防线永远在后端——读魔数、白名单、重命名、非 Web 可访问路径,缺一不可。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











