前端安全体系

What — 什么是前端安全体系

前端安全体系是一套从架构层面保障 Web 应用安全的系统方案,涵盖传输安全、输入输出安全、认证授权、内容安全策略、隐私保护、依赖安全等多个维度,而非单一的漏洞防护。

安全威胁全景

维度威胁影响
传输层中间人攻击、数据窃听数据泄露、会话劫持
注入类XSS、HTML 注入、模板注入脚本执行、Cookie 窃取
请求伪造CSRF、点击劫持冒充用户操作
认证会话会话固定、Token 泄露身份冒充
内容安全恶意脚本加载、CDN 劫持代码执行、数据窃取
隐私合规未授权数据收集、追踪法律风险、用户流失
供应链恶意依赖、包劫持后门植入
客户端存储localStorage 篡改、存储型攻击数据篡改、逻辑绕过

安全防御层次

┌─────────────────────────────────────┐
│         用户浏览器                    │
│  ┌───────────────────────────────┐  │
│  │  CSP / HTTPS / SRI            │  │  ← 传输与内容安全
│  ├───────────────────────────────┤  │
│  │  输入过滤 / 输出编码 / 沙箱     │  │  ← 注入防护
│  ├───────────────────────────────┤  │
│  │  CSRF Token / SameSite / CORS │  │  ← 请求安全
│  ├───────────────────────────────┤  │
│  │  Cookie Secure / Token 安全    │  │  ← 认证安全
│  ├───────────────────────────────┤  │
│  │  存储加密 / 隐私合规           │  │  ← 数据安全
│  └───────────────────────────────┘  │
└─────────────────────────────────────┘

Why — 为什么需要体系化安全

  1. 单点防护不够:修了 XSS 但没有 CSP,一个遗漏就全线崩溃
  2. 合规要求:GDPR、等保 2.0、《个人信息保护法》要求系统性保障
  3. 供应链风险:前端依赖数量庞大(平均 1000+),每个都是攻击面
  4. 攻击自动化:攻击者使用自动化工具批量扫描,体系化防御提高门槛
  5. 用户信任:安全事故导致用户流失,修复成本远高于预防成本

How — 怎么建设

1. 传输安全 — HTTPS

// 强制 HTTPS(HSTS)
// 服务端响应头
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

// 前端检测
if (location.protocol !== 'https:' && location.hostname !== 'localhost') {
  location.replace(`https:${location.href.substring(location.protocol.length)}`)
}
# Nginx 配置 HSTS
server {
    listen 443 ssl;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
}

混合内容:HTTPS 页面加载 HTTP 资源会被浏览器拦截(被动内容降级,主动内容阻止)。解决方案:所有资源走 HTTPS,使用 upgrade-insecure-requests

<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">

2. XSS 防护

2.1 输出编码

// HTML 编码
function encodeHTML(str) {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#x27;')
}

// JS 编码(防止 JS 上下文注入)
function encodeJS(str) {
  return str.replace(/[\\"']/g, '\\$&')
    .replace(//g, '\\0')
    .replace(/
/g, '\\u2028')
    .replace(/
/g, '\\u2029')
}

// URL 编码
function encodeURL(str) {
  return encodeURIComponent(str)
}

2.2 React/Vue 自动转义

// React 默认转义,安全
<div>{userInput}</div>

// dangerouslySetInnerHTML 必须消毒
import DOMPurify from 'dompurify'
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userInput) }} />
<!-- Vue 默认转义,安全 -->
<div>{{ userInput }}</div>

<!-- v-html 必须消毒 -->
<div v-html="sanitize(userInput)"></div>

2.3 DOMPurify 消毒

import DOMPurify from 'dompurify'

// 基础用法
const clean = DOMPurify.sanitize(dirtyHTML)

// 自定义允许标签
const clean = DOMPurify.sanitize(dirtyHTML, {
  ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a'],
  ALLOWED_ATTR: ['href', 'title'],
  FORBID_TAGS: ['style', 'script'],
  FORBID_ATTR: ['onerror', 'onload']
})

// 允许 data-* 属性
DOMPurify.sanitize(dirtyHTML, { ADD_ATTR: ['data-id'] })

3. CSRF 防护

// 1. SameSite Cookie(最简方案)
// 服务端设置
Set-Cookie: sessionId=xxx; SameSite=Strict; Secure; HttpOnly

// SameSite 三个值:
// Strict — 跨站请求完全不带 Cookie(最安全但影响体验)
// Lax   — 导航到目标网站的 GET 请求带 Cookie(默认值,平衡安全与体验)
// None  — 跨站请求也带 Cookie(必须配合 Secure)

// 2. CSRF Token
// 服务端生成 Token,前端提交时携带
fetch('/api/data', {
  method: 'POST',
  headers: {
    'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content
  },
  body: JSON.stringify(data)
})

// 3. Double Submit Cookie
// 请求同时通过 Cookie 和 Header 传递 Token,服务端比对一致
const token = getCookie('csrf_token')
fetch('/api/data', {
  method: 'POST',
  headers: { 'X-CSRF-Token': token },
  credentials: 'same-origin'
})

// 4. 检查 Origin / Referer
// 服务端验证请求头
app.use((req, res, next) => {
  const origin = req.headers.origin || req.headers.referer
  if (origin && !origin.startsWith('https://myapp.com')) {
    return res.status(403).json({ error: 'Forbidden origin' })
  }
  next()
})

4. CSP(内容安全策略)

<!-- 基础 CSP -->
<meta http-equiv="Content-Security-Policy"
  content="default-src 'self';
           script-src 'self' https://cdn.example.com;
           style-src 'self' 'unsafe-inline';
           img-src 'self' data: https:;
           connect-src 'self' https://api.example.com;
           font-src 'self' https://fonts.gstatic.com;
           frame-ancestors 'none';
           base-uri 'self';
           form-action 'self'">
// 报告模式(不拦截,只报告)——先观察再启用
// Content-Security-Policy-Report-Only: ...

// 收集违规报告
// Report-To: { "url": "/api/csp-report", "max_age": 10886400 }
// 动态添加 nonce(服务端渲染)
// 每次请求生成随机 nonce
app.get('*', (req, res) => {
  const nonce = crypto.randomBytes(16).toString('base64')
  res.setHeader('Content-Security-Policy',
    `script-src 'nonce-${nonce}' 'strict-dynamic'; object-src 'none'`
  )
  res.render('index', { nonce })
})

// HTML 中使用 nonce
// <script nonce="{{nonce}}">
//   console.log('trusted code')
// </script>

CSP 关键指令

指令作用示例
default-src所有资源默认策略'self'
script-srcJS 来源限制'self' 'nonce-xxx'
style-srcCSS 来源限制'self' 'unsafe-inline'
img-src图片来源限制'self' data: https:
connect-srcXHR/Fetch/WebSocket 限制'self' https://api.com
frame-ancestors嵌入限制(防点击劫持)'none'
report-uri违规报告地址/csp-report

5. 点击劫持防护

<!-- 方式1:X-Frame-Options(旧方案) -->
<!-- X-Frame-Options: DENY | SAMEORIGIN | ALLOW-FROM origin -->

<!-- 方式2:CSP frame-ancestors(推荐) -->
<!-- Content-Security-Policy: frame-ancestors 'none' -->
<!-- Content-Security-Policy: frame-ancestors 'self' https://trusted.com -->
// 方式3:JS 检测(兜底方案)
if (window.top !== window.self) {
  window.top.location = window.self.location
}

6. 认证与会话安全

// Cookie 安全配置
// Set-Cookie: token=xxx;
//   HttpOnly      — JS 无法读取,防 XSS 窃取
//   Secure        — 仅 HTTPS 传输
//   SameSite=Lax  — 防 CSRF
//   Path=/api     — 限制作用路径
//   Domain=.app.com — 限制作用域名

// JWT 安全实践
// ❌ 不安全:存 localStorage
localStorage.setItem('token', jwt)

// ✅ 安全:存 HttpOnly Cookie
// 后端 Set-Cookie 设置 HttpOnly + Secure + SameSite

// Token 刷新策略
let refreshPromise = null

async function request(url, options = {}) {
  const token = getToken()
  const headers = { Authorization: `Bearer ${token}`, ...options.headers }

  let res = await fetch(url, { ...options, headers })

  // Token 过期,自动刷新
  if (res.status === 401 && !options._retry) {
    if (!refreshPromise) {
      refreshPromise = refreshToken().finally(() => { refreshPromise = null })
    }
    const newToken = await refreshPromise
    headers.Authorization = `Bearer ${newToken}`
    res = await fetch(url, { ...options, headers, _retry: true })
  }
  return res
}

7. SRI(子资源完整性)

<!-- 防止 CDN 被劫持后篡改 JS 文件 -->
<script
  src="https://cdn.example.com/lib.js"
  integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
  crossorigin="anonymous"
></script>

<link
  rel="stylesheet"
  href="https://cdn.example.com/style.css"
  integrity="sha384-abc123..."
  crossorigin="anonymous"
/>
# 生成 SRI 哈希
curl https://cdn.example.com/lib.js | openssl dgst -sha384 -binary | openssl base64 -A

8. 存储安全

// 敏感数据不要存 localStorage/sessionStorage
// ❌
localStorage.setItem('password', password)
localStorage.setItem('token', token)

// ✅ 敏感数据存 HttpOnly Cookie
// ✅ 非敏感数据可以存 localStorage,但要加密
import CryptoJS from 'crypto-js'

const SECRET_KEY = 'your-secret-key' // 从环境变量获取

function encrypt(data) {
  return CryptoJS.AES.encrypt(JSON.stringify(data), SECRET_KEY).toString()
}

function decrypt(cipherText) {
  const bytes = CryptoJS.AES.decrypt(cipherText, SECRET_KEY)
  return JSON.parse(bytes.toString(CryptoJS.enc.Utf8))
}

// 存储加密数据
localStorage.setItem('preferences', encrypt(userPrefs))

// 读取解密
const prefs = decrypt(localStorage.getItem('preferences'))
// IndexedDB 安全注意事项
// 1. 不存储敏感数据
// 2. 数据验证:读取后校验数据格式
// 3. 加密存储
// 4. 设置过期时间

class SecureStorage {
  constructor(dbName, storeName) {
    this.dbName = dbName
    this.storeName = storeName
  }

  async set(key, value, ttl = 3600000) {
    const record = {
      value,
      expiry: Date.now() + ttl
    }
    // IndexedDB 存储逻辑...
  }

  async get(key) {
    const record = await this._getRecord(key)
    if (!record) return null
    if (Date.now() > record.expiry) {
      await this.delete(key)
      return null
    }
    return record.value
  }
}

9. CORS 安全配置

// 服务端 CORS 配置(Koa 示例)
app.use(async (ctx, next) => {
  // ❌ 不安全:允许所有来源
  // ctx.set('Access-Control-Allow-Origin', '*')

  // ✅ 安全:白名单校验
  const allowedOrigins = [
    'https://www.myapp.com',
    'https://admin.myapp.com'
  ]
  const origin = ctx.headers.origin
  if (allowedOrigins.includes(origin)) {
    ctx.set('Access-Control-Allow-Origin', origin)
    ctx.set('Vary', 'Origin') // 防止缓存错乱
  }

  ctx.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE')
  ctx.set('Access-Control-Allow-Headers', 'Content-Type, Authorization')
  ctx.set('Access-Control-Allow-Credentials', 'true')
  ctx.set('Access-Control-Max-Age', '86400') // 预检缓存 24h

  if (ctx.method === 'OPTIONS') {
    ctx.status = 204
    return
  }
  await next()
})

10. 隐私合规

// Cookie 同意管理
class CookieConsent {
  constructor() {
    this.categories = {
      necessary: true,    // 必要 Cookie,默认开启
      analytics: false,   // 分析 Cookie,需用户同意
      marketing: false    // 营销 Cookie,需用户同意
    }
  }

  init() {
    const saved = localStorage.getItem('cookie_consent')
    if (saved) {
      this.categories = JSON.parse(saved)
      this.applyConsent()
    } else {
      this.showBanner()
    }
  }

  acceptAll() {
    this.categories.analytics = true
    this.categories.marketing = true
    this.save()
  }

  acceptNecessary() {
    this.categories.analytics = false
    this.categories.marketing = false
    this.save()
  }

  save() {
    localStorage.setItem('cookie_consent', JSON.stringify({
      categories: this.categories,
      timestamp: Date.now()
    }))
    this.applyConsent()
  }

  applyConsent() {
    if (this.categories.analytics) {
      this.loadAnalytics()
    }
    if (this.categories.marketing) {
      this.loadMarketing()
    }
  }

  loadAnalytics() {
    // 加载 Google Analytics 等
  }

  loadMarketing() {
    // 加载广告追踪等
  }
}

11. 安全响应头清单

# Nginx 安全头配置
add_header X-Content-Type-Options "nosniff" always;           # 禁止 MIME 嗅探
add_header X-Frame-Options "DENY" always;                     # 禁止嵌入 iframe
add_header X-XSS-Protection "0" always;                       # 关闭旧 XSS 过滤器(CSP 替代)
add_header Referrer-Policy "strict-origin-when-cross-origin"; # 控制 Referer 泄露
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(self)"; # 限制浏览器 API
add_header Content-Security-Policy "default-src 'self'" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
响应头作用推荐值
Strict-Transport-Security强制 HTTPSmax-age=31536000; includeSubDomains
X-Content-Type-Options禁止 MIME 嗅探nosniff
X-Frame-Options防点击劫持DENY
Content-Security-Policy内容安全策略按需配置
Referrer-Policy控制 Refererstrict-origin-when-cross-origin
Permissions-Policy限制浏览器 API按需禁用
Cross-Origin-Opener-Policy隔离跨域窗口same-origin
Cross-Origin-Resource-Policy防跨域资源泄露same-origin

12. 安全审计与自动化

# GitHub Actions 安全扫描
name: Security Scan
on: [push, pull_request, schedule]
jobs:
  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # npm 依赖审计
      - run: npm audit --audit-level=high

      # Snyk 安全扫描
      - uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}

      # ESLint 安全插件
      - run: npx eslint --plugin security src/

      # 检查密钥泄露
      - uses: gitleaks/gitleaks-action@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
// eslint-plugin-security 配置
// .eslintrc.js
module.exports = {
  plugins: ['security'],
  extends: ['plugin:security/recommended'],
  rules: {
    'security/detect-object-injection': 'warn',
    'security/detect-non-literal-regexp': 'warn',
    'security/detect-unsafe-regex': 'error',
    'security/detect-eval-with-expression': 'error',
    'security/detect-non-literal-fs-filename': 'warn'
  }
}

常见问题与踩坑

问题原因解决方案
CSP 阻止合法脚本策略过严或未覆盖内联脚本使用 nonce 或 Report-Only 模式调试
SRI 更新麻烦每次更新 CDN 文件需重新算哈希CI 自动生成 SRI 哈希
CORS 预检频繁每次跨域请求先发 OPTIONS设置 Access-Control-Max-Age 缓存预检
SameSite 影响第三方登录Strict 模式下 OAuth 回调不带 Cookie登录流程用 Lax,其他用 Strict
localStorage 被篡改前端存储无保护关键数据加密 + 签名校验
HTTPS 混合内容部分资源仍是 HTTP全面升级 HTTPS + upgrade-insecure-requests

安全检查清单

  • 全站 HTTPS + HSTS
  • Cookie 设置 HttpOnly + Secure + SameSite
  • CSP 策略配置并启用
  • XSS:所有用户输入输出编码,使用 DOMPurify
  • CSRF:SameSite Cookie + Token 双重防护
  • SRI:外部 CDN 资源加完整性校验
  • 响应头:X-Content-Type-Options / X-Frame-Options / Referrer-Policy
  • 认证:JWT 存 HttpOnly Cookie,实现自动刷新
  • 存储:敏感数据不入 localStorage,必要数据加密
  • 依赖:npm audit + Dependabot + SBOM
  • 隐私:Cookie 同意管理 + 最小数据收集
  • 审计:ESLint security 插件 + CI 安全扫描

面试题

1. 前端安全的全链路防护包括哪些环节?各环节如何衔接?

:前端安全全链路包含五个环节:(1) 传输层——HTTPS + HSTS 保证数据加密传输,防止中间人攻击;(2) 入口层——CSP 限制资源加载来源,SRI 校验 CDN 资源完整性,WAF 拦截恶意请求;(3) 应用层——输入校验 + 输出编码防 XSS,CSRF Token + SameSite 防 CSRF,CORS 白名单防跨域滥用;(4) 认证层——HttpOnly Cookie 防 XSS 窃取 Token,SameSite 防 CSRF 利用 Cookie,Token 短有效期 + 刷新机制限制泄露影响;(5) 数据层——敏感数据加密存储,隐私合规(Cookie 同意、最小收集)。各环节衔接:HTTPS 是基础,没有它 Cookie 的 Secure 和 SameSite 都无效;CSP 是 XSS 的兜底防线,即使编码遗漏也能拦截脚本执行;CSRF Token 依赖 Cookie 的 SameSite 配合才完整。任何单点防护都有盲区,必须多层纵深防御。


2. CSP 的 nonce 和 hash 方式有什么区别?各自的适用场景?

:(1) Nonce 方式——每次请求服务端生成随机字符串,CSP 头中声明 script-src 'nonce-abc123',HTML 中 <script nonce="abc123"> 标记可信脚本。只有 nonce 匹配的脚本才能执行,攻击者无法猜到 nonce 值。适合 SSR 项目,服务端每次渲染时动态生成 nonce。(2) Hash 方式——对脚本内容计算 SHA256/384/512 哈希,CSP 头中声明 script-src 'sha256-xxx'。只有内容哈希匹配的脚本才能执行。适合脚本内容固定的场景(如内联配置)。区别:nonce 每次请求不同,更灵活;hash 基于内容,脚本修改需同步更新 CSP。推荐组合:'strict-dynamic' + nonce,nonce 授权的脚本动态加载的子脚本自动信任,无需逐个声明。


:HttpOnly 阻止 JS 读取 Cookie,但不代表绝对安全。绕过方式:(1) CSRF——虽然读不到 Cookie 值,但浏览器仍会自动携带,攻击者可以构造请求让浏览器自动带上 Cookie;(2) 网络层嗅探——如果未配置 Secure 标志,HTTP 请求中 Cookie 明文传输,中间人可截获;(3) 子域名泄露——Cookie 的 Domain 设置为 .example.com 时,子域名 evil.example.com 的 XSS 可以跨读;(4) 服务端日志——Cookie 每次请求发送到服务端,如果服务端日志未脱敏,Cookie 值可能出现在日志中;(5) 浏览器漏洞——极少数浏览器漏洞允许绕过 HttpOnly 限制(如历史上的 UTF-7 编码绕过)。正确做法:HttpOnly + Secure + SameSite + 合理 Domain + 合理 Path,多层防护。


4. 什么是供应链攻击?前端如何防范?

:供应链攻击是指攻击者通过篡改项目的上游依赖(npm 包)来影响所有下游用户。典型方式:(1) 恶意包——发布与知名包名近似的包(Typosquatting),如 crossenv 冒充 cross-env;(2) 包劫持——获取维护者账号控制权,在原包中注入恶意代码(event-stream 事件);(3) 依赖混淆——在公共 registry 注册与公司内部私有包同名的包;(4) Install Scripts——postinstall 钩子在安装时执行恶意命令。防范措施:(1) lockfile 冻结——CI 用 --frozen-lockfile,保证安装版本一致;(2) 精确版本——save-exact=true,避免版本范围;(3) 禁用 scripts——ignore-scripts=true;(4) npm audit——定期扫描已知漏洞;(5) 作用域 registry——私有包 @company/ 指向私有 registry,防依赖混淆;(6) SBOM——生成软件物料清单,快速定位受影响依赖;(7) Snyk/Socket——实时监控依赖安全。


5. 如何设计一个安全的前端 Token 存储和刷新方案?

:方案设计:(1) Access Token 存 HttpOnly Cookie——JS 无法读取,防 XSS 窃取。设置 Secure(仅 HTTPS)、SameSite=Lax(防 CSRF)、Path=/api(只对 API 请求携带,减少暴露面);(2) Refresh Token 存 HttpOnly Cookie——独立于 Access Token,Path 设为 /api/auth/refresh,只有刷新接口携带;(3) 前端无感知刷新——请求 401 时自动调用刷新接口获取新 Token,对调用方透明。用 Promise 缓存防止并发刷新(多个请求同时 401 只刷新一次);(4) 刷新失败——跳转登录页;(5) CSRF 防护——虽然 Token 存 Cookie,但 SameSite=Lax + CSRF Token 双重防护。关键点:前端 JS 永远不接触 Token 明文,只通过 Cookie 自动携带。若必须前端携带(如跨域 API),则用 Authorization Header + CSRF Token,Token 存内存(不持久化),刷新时通过 iframe 或同域接口获取。


6. CSP 报告模式怎么用?如何从报告模式过渡到强制模式?

:CSP 报告模式使用 Content-Security-Policy-Report-Only 响应头替代 Content-Security-Policy,浏览器不会拦截违规请求,只会将违规信息发送到 report-uri 指定的地址。过渡步骤:(1) 制定目标策略——梳理所有合法资源来源,编写完整 CSP 规则;(2) 启用报告模式——先设置 Report-Only,配置 report-uri 收集违规报告;(3) 分析报告——观察 1-2 周,检查是否有合法资源被误报(如第三方 SDK、统计代码的内联脚本);(4) 调整策略——根据报告逐步添加白名单,用 nonce/hash 处理必要的内联脚本;(5) 切换强制模式——确认报告为零或极少误报后,从 Report-Only 切换到 Content-Security-Policy;(6) 持续监控——保留 report-uri,实时发现新的违规。建议使用 strict-dynamic + nonce 方案,避免维护过长的白名单。


7. 前端如何检测和防御点击劫持?

:点击劫持是攻击者将目标网站嵌入透明 iframe,覆盖在看似无害的按钮上,诱导用户点击。防御方式:(1) X-Frame-Options——HTTP 响应头 DENY(完全禁止嵌入)或 SAMEORIGIN(仅同源可嵌入)。简单有效但不够灵活;(2) CSP frame-ancestors——Content-Security-Policy: frame-ancestors 'none'frame-ancestors 'self' https://trusted.com。比 X-Frame-Options 更灵活,支持白名单,是推荐方案;(3) JS 检测兜底——if (window.top !== window.self) { window.top.location = window.self.location },但攻击者可以用 sandbox 属性禁用 JS;(4) UI 层防御——关键操作(支付、删除)增加二次确认弹窗或验证码,即使被劫持点击,用户也能看到真实操作;(5) Cookie SameSite——SameSite=Strict 使得跨站 iframe 中的请求不带 Cookie,API 返回 401。


8. 如何对一个现有前端项目做安全审计?给出完整流程。

:完整审计流程分五步:(1) 信息收集——梳理项目技术栈、第三方依赖(npm ls --all)、外部资源加载(CDN、第三方 SDK)、API 接口清单、认证方案(JWT/Session/Cookie 配置);(2) 自动化扫描——npm audit 检查依赖漏洞、snyk test 深度扫描、eslint-plugin-security 检查代码安全问题、gitleaks 检查密钥泄露、浏览器 Lighthouse 安全审计;(3) 手动代码审查——重点检查:innerHTML/v-html/dangerouslySetInnerHTML 是否消毒、eval()/new Function() 使用、URL 参数直接插入 DOM、localStorage 存储敏感数据、CORS 配置是否过宽、API 是否鉴权;(4) 渗透测试——模拟 XSS 攻击(在各输入点注入脚本)、CSRF 攻击(构造跨站请求)、点击劫持(iframe 嵌入)、Token 泄露场景;(5) 报告与修复——按风险等级(Critical/High/Medium/Low)排列发现项,制定修复优先级和计划,修复后复测。工具推荐:OWASP ZAP(自动化扫描)、Burp Suite(手动渗透)、Security Headers(检查响应头)。


相关链接