别让一个输入框毁了整个系统
很多人觉得,只要不写后台代码就不用操心安全问题。可现实是,前端随便放个输入框,比如用户评论、搜索框、甚至个人签名,黑客就能通过这些地方注入恶意脚本。这种攻击叫跨站脚本(XSS),轻则弹个广告窗,重则直接偷走登录凭证。
在设计网络应用架构时,不能把安全当成后期补丁。从一开始就要考虑怎么拦住这类攻击。
输入过滤不是万能的
很多开发者习惯在前端用 JavaScript 拦截危险字符,比如 <script>。但这根本没用——用户可以关掉 JS,或者用工具直接发请求。真正该做的是在服务端对所有输入进行清理和验证。
比如用户昵称里不允许出现任何标签,那就得在后端强制转义特殊字符。像 < 变成 <,> 变成 >。这样就算有人提交了“<script>alert('hacked')</script>”,页面显示的也只是普通文本。
输出编码更关键
同样的数据,在不同位置需要不同的编码方式。如果内容要插入 HTML 体,就得做 HTML 实体编码;如果放在 JavaScript 字符串里,就得做 JS 转义;要是进属性值,还得单独处理引号。
举个例子:
const userName = "张三<img src=x onerror=alert(1)>";
document.getElementById('welcome').innerHTML = '欢迎你,' + userName;
这段代码看着没问题,但一旦 userName 包含恶意 payload,就会执行脚本。正确做法是使用 textContent 或先做 HTML 转义:
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}善用浏览器自带防线:CSP
内容安全策略(CSP)是现代 Web 应用的重要屏障。通过设置 HTTP 头,告诉浏览器只允许加载指定来源的脚本。
比如这行响应头:
Content-Security-Policy: default-src 'self'; script-src 'self' trusted-cdn.com; object-src 'none';意思是:所有资源默认只能从当前域名加载,脚本还可以来自 trusted-cdn.com,禁止加载 Flash 等插件。这样一来,即使黑客成功注入了内联脚本,浏览器也会直接阻止执行。
Cookie 加个保护罩
用户的登录状态通常存在 Cookie 里。如果被 XSS 攻击读取到,账号立马就不安全了。所以得给关键 Cookie 加上 HttpOnly 和 Secure 标志。
设置了 HttpOnly 后,JavaScript 就没法通过 document.cookie 读取它;Secure 则保证只在 HTTPS 下传输。这两项在服务端设一下就行:
Set-Cookie: sessionid=abc123; Path=/; HttpOnly; Secure; SameSite=Lax模板引擎也能帮忙
现在很多项目用模板渲染页面,像 Handlebars、Vue、React 这些,默认会对变量插值做转义。但要注意别乱用“绕过转义”的功能,比如 Handlebars 的 {{{ }}} 或 Vue 的 v-html。
除非你百分百确定内容是可信的,否则永远用安全的插值方式。别为了省事打开漏洞口子。
安全不是某个模块的事,而是整个架构都要参与的协作。从输入、处理到输出,每一环都得设防,才能挡住 XSS 这种常见又危险的攻击。