前端安全

105 阅读2分钟

前端不仅是美化页面或提升用户体验,更承担着保护用户数据和系统安全的重要责任。每一次表单提交、接口请求或动态交互,都可能成为攻击入口。前端开发者必须关注网络安全,如防止 XSS、CSRF、数据泄露等风险,设计安全的输入验证、权限控制和加密传输,确保应用既好看又安全,为用户和企业提供可靠保障。

1. XSS(Cross-Site Scripting)—— 类型与底层防护

1.1 三类 XSS 概览(一句话理解)

  • 反射型(Reflected) :恶意输入随请求被服务器“反射”到响应并执行。
  • 存储型(Stored) :恶意载体存储在数据库 / 评论 / 用户资料等,后续被其他用户触发。
  • DOM-based:漏洞完全在客户端 JS 层(例如直接将 location.hash 写入 innerHTML)。
    官方参考:OWASP XSS

1.2 攻击链原理图

dom_xss.svg

1.3 底层防护原则(按优先级)

  1. 输出编码(Output Encoding) :上下文敏感编码是最根本防线。使用成熟库,如 lodash.escape
  2. 避免危险 API:尽量不要用 innerHTMLdocument.writeeval()new Function()
  3. 安全模板 / 自动转义:现代框架(React/Vue/Angular)默认转义插值,避免使用 v-htmldangerouslySetInnerHTML
  4. CSP(内容安全策略)做第二道防线:禁止 inline script、限制脚本来源、使用 nonce/hash。官方文档:MDN CSP

1.4 上下文敏感编码对比表

写入上下文错误做法正确防护
HTML 内容el.innerHTML = userel.textContent = user 或服务端 HTML 编码
HTML 属性el.setAttribute('title', user)使用属性编码函数
JS 字符串eval("..."+user)JS-String-encode 或避免拼接
URL直接拼接 queryencodeURIComponent(user)

1.5 实战代码片段

Node 服务器端 HTML 转义

const escape = require('lodash.escape');
res.send(`<div>欢迎 ${escape(username)}</div>`);

客户端避免 DOM XSS

<div id="out"></div>
<script>
  const text = decodeURIComponent(location.hash.slice(1) || '');
  document.getElementById('out').textContent = text;
</script>

2. CSRF(Cross-Site Request Forgery)

2.1 原理图

csrf.svg

2.2 防护策略

  1. SameSite Cookie:设置 SameSite=LaxStrictMDN 官方文档
  2. Anti-CSRF Token:服务器保存随机 token,前端提交时校验。官方指南:OWASP CSRF
  3. 验证 Origin / Referer:检查请求头来源。官方文档:MDN HTTP Origin
  4. 高风险操作二次确认:密码、2FA 等。

2.3 实战示例(Express + Fetch)

res.cookie('sid', sid, {
  httpOnly: true,
  secure: true,
  sameSite: 'lax'
});
// server 渲染页面时注入 token
res.render('index', { csrfToken: req.csrfToken() });

// client fetch 请求
fetch('/api/transfer', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content
  },
  body: JSON.stringify({ amount: 100 })
});

3. 点击劫持(Clickjacking)

3.1 原理图

flowchart LR
  A[恶意页面] -->|嵌入 victim.com iframe| B[victim.com]
  A --> C[透明遮罩/按钮置换]
  C --> D[用户点击]
  D -->|实际触发| B[iframe 内按钮]

3.2 防护头

示例:

X-Frame-Options: DENY
Content-Security-Policy: frame-ancestors 'none';

4. 依赖安全(SCA / Supply-Chain)

4.1 风险点

  • npm 包数量庞大,维护者被接管或发布恶意代码。
  • 许可证合规问题可能引发法律风险。
    官方指南:Snyk npm 安全最佳实践

4.2 CI 集成流程

  1. PR 阶段运行 SCA(Snyk / Dependabot / npm audit)。
  2. 使用 Lockfile 并校验未被篡改。
  3. 关键依赖使用私有 registry 或缓存代理。
  4. 维护 SBOM(Software Bill of Materials)。
  5. 手动审查关键依赖源码、提交、issue 活跃度。

4.3 工具示例

  • Dependabot(GitHub)
  • Snyk
  • npm audit / audit-ci

GitHub Actions 示例(Snyk):

name: Snyk Scan
on: [push, pull_request]
jobs:
  snyk:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run Snyk to check for vulnerabilities
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}

5. 常用安全 HTTP 头与 Cookie 基线

Header目的建议值 / 备注
Content-Security-Policy限制内容来源、阻止 inline script使用 nonce/hash
X-Frame-Options防止 iframe 嵌入DENY / SAMEORIGIN
X-Content-Type-Options防止 MIME sniffingnosniff
Strict-Transport-Security强制 HTTPSmax-age=...; includeSubDomains; preload
Referrer-Policy控制 Refererno-referrer-when-downgrade
Permissions-Policy限制浏览器 APIgeolocation=(), microphone=()

Cookie 示例:

Set-Cookie: sid=...; HttpOnly; Secure; SameSite=Lax; Path=/

官方文档:MDN Set-Cookie


6. Checklist & PR 审查要点

  • 输出编码是否做上下文敏感处理?
  • 禁止危险 API / innerHTML / v-html / dangerouslySetInnerHTML?
  • CSP、X-Frame-Options、frame-ancestors 是否配置?
  • Cookie: HttpOnly, Secure, SameSite 是否设置?
  • 依赖安全(Snyk / Dependabot / npm audit)集成 CI?
  • Lockfile 是否校验?SBOM 是否保存?
  • 异常监控 / CSP 报告 / WAF 日志是否接入?

7. 参考官方文档