Skip to main content

概览

前端安全是前端面试中的高频考点。面试官通常会通过“你在项目中遇到过哪些安全问题?”或“说一下 XSS 和 CSRF 的区别及防范”来考察。以下是前端常见安全问题的系统化总结,专为面试准备。

1. XSS (Cross-Site Scripting) 跨站脚本攻击

原理

攻击者通过在目标网站上注入恶意脚本,使之在用户的浏览器上运行,从而获取用户的敏感信息(如 Cookie、SessionID 等)或接管用户会话。

分类

  1. 存储型(Stored XSS):恶意脚本被持久化保存在目标服务器上(如评论区、留言板)。当其他用户访问页面时,脚本从数据库中取出并执行。
  2. 反射型(Reflected XSS):恶意脚本作为网络请求的一部分发送给服务器,服务器又把该脚本“反射”回浏览器(如搜索框带参数)。攻击者通常通过诱导用户点击包含恶意代码的 URL 来实施。
  3. DOM 型(DOM-based XSS):纯前端漏洞。攻击者构造出特殊的 URL,前端 JavaScript 代码在解析 URL 参数或用户输入时,直接执行了恶意代码,全过程不经过服务器参与。

防范策略

  • 输入过滤与转义:对用户输入进行严格处理。
  • 输出转义 (核心防御):在将内容插入到 HTML 页面前,将特殊字符转换为 HTML 实体
    • 原理:XSS 的本质是“误把数据当代码执行”。比如黑客输入 <script>alert(1)</script>,如果直接渲染,浏览器会把它当成脚本执行。
    • 转义后:字符会被替换为 &lt;script&gt;alert(1)&lt;/script&gt;
    • 结果:浏览器看到 &lt; 时,知道这只是一个要展示的“小于号”文本,而不会把它识别为 HTML 标签的开始。这样,攻击脚本就从“可执行的代码”降级为了“纯粹的字符串文本”。
  • 设置 HttpOnly Cookie:禁止 JavaScript 读取某些敏感 Cookie(document.cookie 无法读取),防止被恶意脚本窃取。
  • CSP (Content Security Policy):内容安全策略。通过设置 HTTP Header Content-Security-Policy,严格限制网页可以加载和执行的外部资源。
  • 现代框架的默认防御
    • 面试追问:React 如何防范 XSS?
    • 回答:React 在渲染 JSX 之前,默认会将所有字符串变量转义。如果是必须要直接插入 HTML,需要使用 dangerouslySetInnerHTML 属性,这就需要开发者自己结合 DOMPurify 等库保证数据安全。

面试实战题:如果不使用框架,原生 JS 怎么快速转义字符串?可以用 escape() 吗?

绝对不能用 escape() 这是一个被废弃的 API,且它的作用是 URL 编码(类似于 encodeURI),根本无法防御 HTML 注入。

正确做法 1:手动正则替换 (最轻量)

function escapeHTML(str) {
const escapeMap = {
"&": "&amp;",
"<": "&lt;",
">": "&gt;",
'"': "&quot;",
"'": "&#39;",
};
return str.replace(/[&<>"']/g, (s) => escapeMap[s]);
}

正确做法 2:利用浏览器 DOM (最巧妙) 借用浏览器自带的 textContent 自动转义特性:

function safeEscape(str) {
const div = document.createElement("div");
div.textContent = str;
return div.innerHTML;
}

正确做法 3:生产环境推荐 使用成熟的库如 lodash/escape 或专门的 XSS 库如 xssDOMPurify。因为 XSS 场景非常复杂(如属性注入、JavaScript 伪协议等),正则很难覆盖全。

2. CSRF (Cross-Site Request Forgery) 跨站请求伪造

原理与攻击流程

CSRF 的核心在于:利用浏览器在发起请求时会自动携带目标网站 Cookie 的特性,冒充受害者发送恶意请求。

为了更好理解,我们可以拆解一个典型的“银行转账”攻击流程:

  1. 用户登录:受害者登录了合法网站 bank.com,浏览器存储了代表登录状态的 Cookie
  2. 诱导访问:受害者在未退出 bank.com 的情况下,被诱导访问了黑客的恶意网站 hacker.com
  3. 发起请求hacker.com 的页面代码中隐藏了一个向 bank.com 发起的请求。
    • 例如一个隐藏表单:<form action="https://bank.com/transfer" method="POST">
    • 表单字段包含恶意数据:<input name="to" value="黑客账号">
  4. 自动带上凭证:浏览器在向 bank.com 发起请求时,发现本地有 bank.com 的 Cookie,于是自动将其塞进请求头中发送。
  5. 服务端误判bank.com 的服务器收到请求,验证 Cookie 发现是受害者的合法会话,于是执行了转账操作。

核心结论:黑客自始至终没有拿到你的 Cookie 内容,他只是“借用”了浏览器自动发送 Cookie 的机制,完成了跨站点的身份冒用。

面试高频:XSS 和 CSRF 的区别?

  • XSS 是利用用户对指定网站的信任,注入恶意脚本执行。
  • CSRF 是利用网站对用户的信任,冒充用户发起请求(不需要获取 Cookie 的具体内容,只是利用浏览器会自动携带 Cookie 的机制)。

防范策略

  • CSRF Token (业界主流方案):服务器在用户登录后下发一个随机 Token(存入 sessionStorage 或 DOM 中)。每次请求时由前端手动放入请求参数或 Header。
    • 核心原理:黑客可以冒用 Cookie,但黑客无法获取存储在页面 DOM 或 sessionStorage 中的 Token(受同源策略限制)。
    • 存在的问题一旦页面存在 XSS 漏洞,Token 就会被黑客脚本轻松读取并利用。即:XSS 可以辅助 CSRF 绕过 Token 防御。
  • 同源检测(Origin / Referer):验证 HTTP 头的 RefererOrigin 字段。
    • 存在的问题:并不 100% 可靠。出于隐私保护,某些浏览器或防火墙会过滤掉 Referer;且在某些低版本浏览器下,Origin 字段可能缺失。
  • 双重 Cookie 验证:在请求参数中加入一个随机生成的 Cookie 值,服务端验证参数中的值和真实 Cookie 是否一致。
  • Cookie 的 SameSite 属性 (现代浏览器最强防御)
    • 原理:CSRF 攻击之所以能成功,全靠浏览器在跨站请求时“自作聪明”地自动带上 CookieSameSite 属性就是告诉浏览器:如果是跨站请求,不准自动带上这个 Cookie
    • 为什么能避免 CSRF:黑客诱导你从 hacker.com 发起对 bank.com 的请求时,如果 bank.com 的 Cookie 设置了 SameSite=Strict/Lax,浏览器发现请求源和目标源不一致,就不会发送该 Cookie。没有了身份凭证(Cookie),黑客发起的请求在服务端就会被判定为未登录,攻击自然失效。
    • 属性值
      • Strict:最为严格。完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。
      • Lax:适度。导航到目标网址的 GET 请求(如点击链接跳转)会带上,但 Ajax、Post、iframe 等跨站请求不会带上。(现代浏览器默认值)
      • None:关闭限制。任何情况都会发送(必须配合 Secure 属性)。

3. 点击劫持 (Clickjacking)

原理

攻击者将需要攻击的网站通过 iframe 嵌套在自己的网页中,并将 iframe 设置为透明,在页面中透出一个诱导用户点击的按钮。用户以为点击的是当前页面的按钮,实际上点击了被嵌套网页的按钮(如点赞、转账等)。

防范策略

  • X-Frame-Options 响应头
    • DENY:页面不允许在 iframe 中展示。
    • SAMEORIGIN:该页面可以在相同域名页面的 iframe 中展示。
    • ALLOW-FROM uri:该页面可以在指定来源的 iframe 中展示。
  • CSP 的 frame-ancestors 指令:替代 X-Frame-Options 的现代方案。
  • JS 防御:判断顶层窗口与当前窗口是否一致 (if (window.top !== window.self) { window.top.location = window.location; })。

4. 网络劫持与中间人攻击 (MITM)

原理

攻击者在通信两端之间拦截、窃听或篡改数据。常见的有:

  • DNS 劫持:篡改 DNS 解析,将域名指向恶意 IP。
  • HTTP 劫持:在用户和服务器通信时,篡改 HTTP 报文内容(如部分运营商强行插入广告)。

防范策略

  • 全站 HTTPS:通过 SSL/TLS 协议对数据进行加密,防止数据被窃听和篡改。同时通过数字证书验证服务器身份。
  • HSTS (HTTP Strict Transport Security):强制浏览器只能通过 HTTPS 与服务器交互,防止降级攻击。

5. SQL 注入

原理

攻击者在请求参数中注入恶意 SQL 语句,导致数据库执行非法操作。(前端了解即可,主要靠后端防范)。

防范策略

  • 参数化查询(预编译):不直接拼接 SQL 字符串。
  • 后端严格校验:对输入参数进行严格的类型校验和特殊字符过滤。

6. 其他常见安全防护

接口防刷 / 暴力破解

接口被刷会导致服务器崩溃或资源被恶意消耗(如短信盗刷)。

  • 验证码机制:关键操作(登录、发送短信等)增加图形验证码、滑块验证码、无感验证。
  • IP / 账号限流:限制短时间内同一个 IP 或账号的高频请求。
  • 前端风控:采集设备指纹、浏览器特征等数据上报给后端进行风险评估。

数据安全与反爬虫

  • 接口加密:重要接口的请求参数和响应结果进行 AES/RSA 混合加密,并在请求头中加入签名(Sign)防篡改。
  • 字体反爬 / CSS 偏移反爬:敏感数据使用自定义字体渲染,或者通过 CSS 将乱序的字符重新排列,使得直接抓取 DOM 无法获取真实数据。

资源完整性校验 (SRI)

如果使用了 CDN 加载第三方资源(如 React/Vue 的 CDN 包),一旦 CDN 被黑客篡改植入恶意代码,网页就会中招。

  • Subresource Integrity (SRI):在 <script> 标签中加入 integrity 属性(包含文件的哈希值)。浏览器下载文件后会核对哈希值,如果不匹配则拒绝执行。
    <script
    src="https://example.com/example-framework.js"
    integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
    crossorigin="anonymous"
    ></script>