CSRF 攻击与防护

跨域(CORS)、Cookies、身份认证、CSRF 攻击与防护、以及不同框架(如 Django 和 FastAPI)对安全机制的实现差异。​ ​ ​​"CSRF 为什么重要"、"为什么 FastAPI 没有自带 CSRF"、"如何在 FastAPI 中实现 CSRF 保护"​,最终形成一个完整的安全认知闭环。💡


一、核心问题链(简化版)

  1. CORS(跨域)并不能真正防止黑客攻击,比如黑客可以通过 Nginx 反向代理等方式,绕过浏览器,直接调用我的后端接口,甚至带上我的 Cookies,那岂不是很危险?​
  2. 那为什么我登录了 https://your-bank.com,而 https://evil.com 通过 Nginx 反向代理访问我的接口,仍然可能带上我的 Cookies?难道不危险吗?​
  3. 那是不是说明 CSRF(跨站请求伪造)防护很重要?因为 CSRF Token 是网站生成的,evil.com 是拿不到的?​
  4. 既然 CSRF 这么重要,为什么我很少听说 FastAPI 提供 CSRF 保护?是 FastAPI 不够安全吗?​
  5. 如何在 FastAPI 中实现类似 Django 那样的 CSRF 保护?​

二、逐个问题深度解析


❓ Q1:CORS 不能防止黑客攻击,通过 Nginx 代理也能调用接口,不是依然很危险吗?

✅ ​是的,你说得完全正确!​

  • CORS 是浏览器的一种安全机制,它的作用是:防止恶意网站的前端 JavaScript 在用户浏览器中,偷偷访问另一个网站(比如你的银行 API)的数据。​

  • 但它并不能阻止以下情况:​

    • 用户自己用 Postman、curl、浏览器直接访问;
    • 恶意网站通过 服务端代理(如 Nginx 反向代理)​ ,把请求转发到你的 API,绕过浏览器
    • 黑客自己写程序(Python、Node.js 等)直接调用你的接口;
    • 如果用户已经登录并且浏览器自动携带了 Cookies,那么这些请求仍可能带上身份信息,从而访问到用户数据。

🔓 ​这就是为什么:CORS 不能作为你后端接口的 "唯一防线",它只是针对浏览器环境下的前端 JS 恶意调用的浅层防护。​


❓ Q2:那为什么登录了 https://your-bank.comhttps://evil.com 通过反向代理,还能带上我的 Cookies 呢?岂不是很危险?

✅ ​非常危险,而且这种情况是真实存在的威胁!​

关键点在于:​Cookies 的作用域和 SameSite 属性。​

1. ​什么是 Cookie?​

  • 当你登录 https://your-bank.com,服务器通常会通过 Set-Cookie 响应头,给你的浏览器设置一个 Session Cookie 或 Token Cookie,用于标识你的登录状态。
  • 浏览器之后访问 https://your-bank.com 的任何请求,都会自动在 HTTP Header 中带上这个 Cookie (如 Cookie: sessionid=xxx)。

2. ​如果 evil.com 设置了一个代理,访问你的 API:​

  • 比如用户访问 https://evil.com/proxy-api,而这个页面背后通过 Nginx 代理把请求转发到 https://your-bank.com/api/private

  • 如果你的 Cookie 没有设置 SameSite 或者设置为 SameSite=None; Secure,并且是 HttpOnly 的,那么:​

    • 浏览器在访问 evil.com 时,如果代理请求是发到 your-bank.com 的,那么浏览器仍然可能自动带上 Cookie!​

3. ​危险根源:​

  • 如果你的 Cookie 是 默认的(SameSite=Lax/None,没有 Secure 限制,没有 CSRF 保护)​ ,那么攻击者可以通过这种方式发动 CSRF 攻击会话劫持

❓ Q3:那 CSRF Token 是不是就很重要?因为 evil.com 拿不到这个 Token?

✅ ​完全正确!这正是 CSRF Token 的核心价值所在!​

什么是 CSRF 攻击?

CSRF(Cross-Site Request Forgery,跨站请求伪造)是指:攻击者诱导用户在已登录某个网站的情况下,访问恶意网站,该网站通过浏览器自动携带用户的身份凭证(如 Cookies),向目标网站发起恶意请求(如转账、修改密码)。

为什么 CSRF Token 能防御?

  • CSRF Token 是服务端生成的一串随机字符串,存储在服务端 Session 或者嵌入到页面表单 / Meta 标签中,每次提交敏感请求时必须带上。​
  • 关键点:这个 Token 不会通过 Cookie 自动发送,而是要由前端页面在渲染时由服务端插入到表单或 HTTP Header 中,恶意网站(如 evil.com)无法通过 JS 从 Cookie 或 DOM 中拿到这个 Token!​
  • 所以,即使 evil.com 能发起请求 + 带上 Cookies,但 如果没有正确的 CSRF Token,你的后端会拒绝这个请求!​

🔐 ​这就是为什么:CSRF Token 是防御 CSRF 攻击的最有效手段之一,也是 Django 默认提供的安全机制。​


❓ Q4:既然 CSRF 这么重要,为什么 FastAPI 很少听到有 CSRF 保护?是它不够安全吗?

❌ ​不是 FastAPI 不安全,而是:​

1. ​FastAPI 是一个面向 API 优先、前后端分离、常常搭配 Token(如 JWT)认证的现代框架。​

  • 在典型的 FastAPI 应用中,身份认证往往使用的是 ​无状态 Token(如 JWT、OAuth2)​,而不是基于 Cookie 的 Session。

  • 当使用 Token(放在 HTTP Authorization Header 里)而不是 Cookie 时,CSRF 攻击基本是无效的!​

    为什么?因为恶意网站无法轻易拿到你前端代码中设置的 Token(比如放在 Authorization: Bearer xxx 中),也无法通过浏览器自动携带它。所以 CSRF 攻击无法成立。

2. ​FastAPI 默认不包含 CSRF,是因为:​

  • 它面向的场景往往是:

    • 前后端分离(React/Vue/Angular 调用 API,Token 放在 Header 里);
    • 移动端 App 调用;
    • 使用 API Key、OAuth 等认证方式;
  • 在这些情况下,CSRF 攻击难以发生,所以 FastAPI 把 CSRF 的实现交给开发者按需添加,而不是默认内置。​

🔧 ​结论:不是 FastAPI 不安全,而是它的典型使用方式天然规避了很多 CSRF 攻击场景,所以没有默认提供。但如果你在 FastAPI 中使用了 Cookie-based Session(比如传统网站登录),那你仍然需要手动实现 CSRF 保护!​


❓ Q5:如何在 FastAPI 中实现 CSRF 保护?

如果你在 FastAPI 中使用了 ​基于 Cookie 的 Session 或身份认证(比如传统的登录模式,把 token/session 存在 cookie 里)​ ,那么你 ​确实需要做 CSRF 防护,就像 Django 那样。


✅ 在 FastAPI 中实现 CSRF 保护的常见方法

方法一:使用 fastapi-csrf-protection 第三方库(推荐)

这是一个专门为 FastAPI 实现 CSRF 防护的库,原理类似于 Django:

🔗 GitHub: github.com/florimondma...

安装:

复制代码
pip install fastapi-csrf-protection

基本用法:

python 复制代码
from fastapi import FastAPI, Depends, Request
from fastapi_csrf_protect import CsrfProtect
from fastapi_csrf_protect.exceptions import CsrfProtectError

app = FastAPI()
csrf_protect = CsrfProtect()

# 中间件或依赖注入方式加载 CSRF 保护
@app.on_event("startup")
async def startup():
    await csrf_protect.init()

@app.exception_handler(CsrfProtectError)
def csrf_protect_exception_handler(request: Request, exc: CsrfProtectError):
    return JSONResponse(status_code=403, content={"detail": "CSRF token missing or invalid"})

@app.post("/protected-route")
async def protected_route(request: Request, csrf_token: str = Depends(csrf_protect)):
    return {"message": "CSRF 验证通过!"}

前端需要在请求时:

  • 从 Cookie 或 HTML Meta 中获取 CSRF Token;
  • 然后在请求头(如 X-CSRF-Token)中携带给后端。

如果你不想用第三方库,也可以手动实现一个简单的 CSRF 保护机制,比如:

  1. 登录成功后,后端生成一个 CSRF Token,存到服务端 Session 或者加密后放入 Cookie;
  2. 前端从 Cookie 读取 CSRF Token(或后端直接渲染到页面 <meta> 标签中);
  3. 前端在每次调用敏感接口(如 POST /api/transfer)时,将 CSRF Token 放在 HTTP Header(如 X-CSRF-Token)中传给后端;
  4. 后端比对 Header 中的 Token 和 Session/Cookie 中的 Token 是否一致,不一致则拒绝请求。

🔐 ​核心思想就是:浏览器自动带的 Cookie 不能作为唯一凭证,必须额外验证一个攻击者无法获取的 Token。​


✅ 总结:安全机制全景图

安全机制 作用 是否能防黑客直接调用 是否能防恶意网站 JS 偷数据 是否需要手动实现
CORS 浏览器限制其它源的前端 JS 访问你的 API ❌ 不能 ✅ 能(限制恶意网站 JS) 可配置,但弱防护
Cookies 用于身份认证(如 Session) ❌ 不能(可被携带) ✅ 可能被自动发送 需设置 SameSite/Secure
CSRF Token 防止恶意网站伪造用户请求 ✅ 能(攻击者拿不到 Token) ✅ 能 ✅ 需要主动实现(Django 默认有,FastAPI 需手动/第三方库)
身份认证(JWT/OAuth/Session)​ 确认用户身份 ✅ 能(需合法 Token) ✅ 能 ✅ 必须
Nginx / 防火墙 / IP 限制 网络层访问控制 ✅ 能(可限制来源) ✅ 能 ✅ 可配置

✅ 最终结论(精炼版)

CORS 本身并不能真正保护你的后端接口免受恶意访问,它只是浏览器为了防止恶意网站通过前端 JS 偷数据而设计的一种浅层防护。真正的攻击者可以通过 Nginx 代理、Postman、curl 等方式绕过 CORS,直接调用你的接口,尤其是如果你的接口依赖 Cookie 身份认证,而又没有 CSRF 保护,那就非常危险。​

这就是为什么 CSRF Token 非常重要:它能防御攻击者伪造用户身份发起请求,因为 Token 是服务端生成、无法被恶意网站获取的。Django 默认提供了 CSRF 防护,而 FastAPI 没有默认提供,是因为它更常用于 API + Token 模式,在这种情况下 CSRF 攻击难以生效。但如果你在 FastAPI 中使用了 Cookie-based 认证,那你仍然需要手动实现 CSRF 保护,可以使用第三方库如 fastapi-csrf-protect 或者自己实现 Token 校验逻辑。​

相关推荐
努力的小雨13 小时前
我一个写Java的,怎么就开始玩K8s和Jenkins了?!
后端·云原生
winrisef13 小时前
Node.js版本管理工具 || 全配置安装
后端·node.js·nvm·asdf·fnm
池易13 小时前
调用后端接口像调用函数一样简单——Fun改变了我的开发方式
后端·go
Shawn_Shawn13 小时前
Spring-Ai-Mcp-Server 快速入门
后端·agent·mcp
心月狐的流火号13 小时前
分布式事务XA模式:基于数据库的2PC
分布式·后端
二闹14 小时前
一文搞懂Python装饰器,还能用它给代码加权限锁!
后端·python
大鱼七成饱14 小时前
10分钟搞懂 Rust 的 & 怎么用
后端
DS小龙哥14 小时前
基于STM32设计的智能音乐练习辅助系统
后端
_風箏14 小时前
SpringBoot【集成p6spy】使用p6spy-spring-boot-starter集成p6spy监控数据库(配置方法举例)
后端
_風箏14 小时前
SpringBoot【集成Druid】监控数据库报错 Failed to bind properties under ‘‘ to javax.sql.DataS
后端