aurora blog
  • JS

    • 基本汇总
    • Date时间
    • Array方法
    • String 方法
    • Object方法
    • RegExp正则
    • Es6 新特性等
    • Event-Loop
    • Http and Https
    • for in和for of区别
    • Web Worker
    • Promise && async
    • 堆内存 & 栈内存
    • JS设计模式探索
    • npm & yarn
    • Fetch和Axios的区别
    • 学习及面试问题整理
    • URL 输入到页面加载过程
    • 跨域&nginx本地项目代理
  • FE框架

    • react

      • 基本用法
      • react生命周期
      • hooks 16.8版本后
      • Route原理
      • Redux源码解析
      • React16 Fiber
      • React-VirtualDOM
      • React事件委托机制
      • React性能优化
      • 状态管理方案对比
      • React 18新特性
    • vue

      • vue 基本用法
      • vue 生命周期
      • VirtualDOM
      • vue 事件委托
      • vue 架构
      • vue 状态管理
      • 问题等
    • React-Native

      • React-Native 基本用法
    • 微前端

      • 遇到的问题
    • 鸿蒙 harmony

      • harmony 基础
  • 构建工具

    • webpack

      • Webpack配置详解
      • Webpack的使用
      • Babel-polyfill
      • webpack面试题
    • vite

      • vite配置详解
      • vite面试题
    • rollup

      • Rollup配置详解
      • rollup面试题
    • 构建工具对比
  • 性能优化

    • 性能优化策略
    • 缓存策略
    • 性能优化面试题
  • 浏览器

    • 浏览器渲染原理
    • 浏览器缓存机制
    • 浏览器面试题
  • 工程化

    • 代码规范
    • 工程化面试题
  • 前端安全

    • XSS 攻击与防护
    • CSRF 攻击与防护
    • 前端安全面试题
  • 移动端开发

    • 移动端适配
    • 移动端开发面试题
  • 前端监控

    • 错误监控
    • 性能监控
    • 前端监控面试题
  • Typescript

    • Typescript详解
  • Servers

    • Nodejs
    • Nginx
  • Git命令

    • git常用规范
  • 数据库

    • mongodb
    • mongodb
  • Other

    • Jenkins自动化部署

CSRF 攻击与防护

  • CSRF 概述
  • CSRF 攻击原理
    • 攻击流程
    • 攻击示例
  • CSRF 攻击类型
    • 1. GET 请求攻击
    • 2. POST 请求攻击
    • 3. JSON 请求攻击
  • CSRF 防护措施
    • 1. CSRF Token
    • 2. SameSite Cookie
    • 3. 验证 Referer/Origin
    • 4. 自定义请求头
    • 5. 双重提交 Cookie
  • 框架防护
    • Express.js
    • Django
    • Spring Security
  • 最佳实践
    • 1. 多层防护
    • 2. 敏感操作额外验证
    • 3. 使用框架防护
    • 4. 定期安全审计
  • 常见问题
    • 1. Token 存储在哪里?
    • 2. Token 如何更新?
    • 3. AJAX 请求如何处理?

CSRF 概述

CSRF (Cross-Site Request Forgery) 跨站请求伪造,攻击者诱导用户访问恶意网站,在用户不知情的情况下执行操作。

CSRF 攻击原理

攻击流程

1. 用户登录正常网站 A
2. 网站 A 设置 Cookie
3. 用户访问恶意网站 B
4. 网站 B 发起对网站 A 的请求
5. 浏览器自动携带 Cookie
6. 网站 A 认为请求来自用户
7. 执行恶意操作

攻击示例

场景:转账操作

<!-- 正常网站转账表单 -->
<form action="https://bank.com/transfer" method="POST">
  <input name="to" value="account123">
  <input name="amount" value="1000">
</form>

<!-- 恶意网站 -->
<img src="https://bank.com/transfer?to=attacker&amount=10000">

用户访问恶意网站时,浏览器会自动发送请求,携带 Cookie,完成转账。

CSRF 攻击类型

1. GET 请求攻击

特点:

  • 利用图片、链接等
  • 简单易实现
  • 不需要用户交互

示例:

<!-- 恶意网站 -->
<img src="https://bank.com/transfer?to=attacker&amount=10000">

2. POST 请求攻击

特点:

  • 需要表单提交
  • 可以隐藏表单
  • 自动提交

示例:

<!-- 恶意网站 -->
<form id="attack" action="https://bank.com/transfer" method="POST">
  <input name="to" value="attacker">
  <input name="amount" value="10000">
</form>
<script>document.getElementById('attack').submit();</script>

3. JSON 请求攻击

特点:

  • 现代应用常用
  • 需要特殊处理
  • 利用 CORS

示例:

// 恶意网站
fetch('https://api.example.com/user/update', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ email: 'attacker@evil.com' }),
  credentials: 'include', // 携带 Cookie
});

CSRF 防护措施

1. CSRF Token

原理:

  • 服务器生成随机 Token
  • 存储在 Session 或 Cookie
  • 请求时验证 Token

实现:

// 服务端生成 Token
const token = crypto.randomBytes(32).toString('hex');
session.csrfToken = token;

// 返回给客户端
res.render('form', { csrfToken: token });

// 客户端提交
<form method="POST">
  <input type="hidden" name="_csrf" value="{{ csrfToken }}">
  <!-- 其他字段 -->
</form>

// 服务端验证
if (req.body._csrf !== session.csrfToken) {
  return res.status(403).send('Invalid CSRF token');
}

双重 Cookie:

// 设置 Cookie
res.cookie('csrf-token', token, { httpOnly: false });

// 客户端读取并发送
const token = document.cookie.match(/csrf-token=([^;]+)/)[1];
fetch('/api/update', {
  headers: {
    'X-CSRF-Token': token,
  },
});

2. SameSite Cookie

设置:

Set-Cookie: sessionId=abc123; SameSite=Strict; Secure

值:

  • Strict:完全禁止跨站携带
  • Lax:GET 请求可以携带
  • None:允许跨站携带(需要 Secure)

效果:

  • 防止跨站请求携带 Cookie
  • 浏览器原生支持

3. 验证 Referer/Origin

检查请求头:

// 验证 Referer
const referer = req.headers.referer;
if (!referer || !referer.startsWith('https://example.com')) {
  return res.status(403).send('Invalid referer');
}

// 验证 Origin
const origin = req.headers.origin;
const allowedOrigins = ['https://example.com'];
if (!allowedOrigins.includes(origin)) {
  return res.status(403).send('Invalid origin');
}

注意:

  • Referer 可能被过滤
  • Origin 更可靠
  • 需要白名单

4. 自定义请求头

设置:

// 客户端
fetch('/api/update', {
  headers: {
    'X-Requested-With': 'XMLHttpRequest',
    'X-Custom-Header': 'value',
  },
});

// 服务端验证
if (!req.headers['x-requested-with']) {
  return res.status(403).send('Missing custom header');
}

原理:

  • 浏览器同源策略限制
  • 跨站请求无法设置自定义头
  • 简单有效

5. 双重提交 Cookie

实现:

// 服务端设置 Cookie
res.cookie('csrf-token', token, { httpOnly: false });

// 客户端读取
const token = getCookie('csrf-token');

// 请求时发送
fetch('/api/update', {
  headers: {
    'X-CSRF-Token': token,
  },
  credentials: 'include',
});

// 服务端验证
const cookieToken = req.cookies['csrf-token'];
const headerToken = req.headers['x-csrf-token'];
if (cookieToken !== headerToken) {
  return res.status(403).send('Invalid CSRF token');
}

框架防护

Express.js

使用 csrf 中间件:

const csrf = require('csurf');
const csrfProtection = csrf({ cookie: true });

app.use(csrfProtection);

app.get('/form', csrfProtection, (req, res) => {
  res.render('form', { csrfToken: req.csrfToken() });
});

app.post('/process', csrfProtection, (req, res) => {
  // 已验证
});

Django

内置 CSRF 保护:

# settings.py
MIDDLEWARE = [
    'django.middleware.csrf.CsrfViewMiddleware',
]

# 模板
<form method="post">
  {% csrf_token %}
  <!-- 表单字段 -->
</form>

Spring Security

配置:

@Configuration
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) {
        http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
        return http.build();
    }
}

最佳实践

1. 多层防护

  • CSRF Token
  • SameSite Cookie
  • 验证 Referer/Origin

2. 敏感操作额外验证

  • 密码确认
  • 二次验证
  • 操作日志

3. 使用框架防护

  • Express csrf
  • Django CSRF
  • Spring Security

4. 定期安全审计

  • 检查防护措施
  • 测试攻击场景
  • 更新依赖

常见问题

1. Token 存储在哪里?

选项:

  • Session(服务端)
  • Cookie(客户端,HttpOnly)
  • 双重 Cookie(客户端,非 HttpOnly)

2. Token 如何更新?

策略:

  • 每次请求后更新
  • 定期更新
  • 固定 Token(不推荐)

3. AJAX 请求如何处理?

方法:

  • 从 Cookie 读取 Token
  • 从 Meta 标签读取
  • 自定义请求头
最近更新:: 2025/11/20 14:50
Contributors: liyulai
Prev
XSS 攻击与防护
Next
前端安全面试题