当前位置: 首页 > news >正文

springboot~传统WEB应用开启CSRF

简单比喻:

想象你在咖啡店会员卡里有钱,你每次消费只需要说“用会员卡支付”。攻击者伪装成服务员,在你面前说“用会员卡转账100元到XXX账户”。因为你已经在咖啡店的系统中“登录”了(身份已认证),系统就会执行这个操作。

CSRF攻击原理:

攻击流程:

  1. 用户登录:用户登录正常的网站A(如银行网站),获得登录凭证(Cookie/Session)
  2. 用户访问恶意网站:用户在同一个浏览器中访问了攻击者的网站B
  3. 恶意请求:网站B通过隐藏表单、图片src、AJAX等方式,向网站A发送请求
  4. 自动携带凭证:浏览器会自动携带网站A的Cookie
  5. 网站A执行请求:网站A看到合法Cookie,误以为是用户的自愿操作

攻击示例:

<!-- 恶意网站上的代码 --> <img src="https://your-bank.com/transfer?to=hacker&amount=10000" width="0" height="0" /> <!-- 或隐藏表单 --> <form action="https://your-bank.com/change-email" method="POST"> <input type="hidden" name="email" value="hacker@evil.com"> </form> <script>document.forms[0].submit();</script>

为什么有时要禁用CSRF保护?

适用禁用场景:

  1. 纯API服务(无浏览器交互)

    # 移动App通过API访问后端 # 使用Token认证(JWT/OAuth),而不是Session Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
  2. 仅提供非状态改变的操作

    GET /api/users # 只读操作,通常不需要CSRF POST /api/transfer # 写操作,需要CSRF
  3. 微服务内部通信

    # 服务间调用使用服务凭证,而不是用户会话 service-to-service: true
  4. 某些特殊框架/场景

    // GraphQL通常使用token而不是session // 或某些实时通信应用

具体框架中的禁用示例:

Spring Security:

@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() // 禁用CSRF .authorizeRequests() .anyRequest().authenticated() .and() .httpBasic(); // 使用HTTP Basic认证 } }

Django:

# settings.py CSRF_COOKIE_SECURE = False # 禁用CSRF # 或针对特定视图 from django.views.decorators.csrf import csrf_exempt @csrf_exempt def api_view(request): pass

CSRF保护机制对比:

保护机制工作原理适用场景
CSRF Token服务器生成Token,表单/请求必须携带传统Web应用
SameSite CookieCookie仅在同站请求中发送现代浏览器支持
双重Cookie验证客户端读取Cookie并附加到请求兼容性较好
Referer检查检查请求来源简单但不可靠
无(禁用)不验证纯API、内部服务

何时应该启用/禁用CSRF?

应该启用CSRF的场景:

  • ✅ 传统的基于Session的Web应用
  • ✅ 用户通过浏览器访问的表单提交
  • ✅ 需要用户交互的操作(转账、修改数据)
  • ✅ 使用Cookie/Session进行身份认证

可以禁用CSRF的场景:

  • ✅ 纯REST API,使用JWT/OAuth Token认证
  • ✅ 仅限移动App访问的后端服务
  • ✅ 微服务间的内部通信
  • ✅ 只读的公共API
  • ✅ 使用其他认证方式(API Key、HMAC签名)

禁用CSRF后的替代安全方案:

# 替代方案示例: 1. JWT Token认证: 每次请求携带: Authorization: Bearer <token> 2. API Key + Secret: 请求签名: X-Signature: sha256(api_secret + request_data) 3. OAuth 2.0: 使用Access Token进行授权 4. CORS限制: Access-Control-Allow-Origin: https://trusted-domain.com 5. Rate Limiting: 限制请求频率防止滥用

最佳实践建议:

// 在Spring中,可以针对不同端点配置不同的CSRF策略 public class SecurityConfig { protected void configure(HttpSecurity http) { http // 对Web页面启用CSRF .csrf(csrf -> csrf .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) .csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler()) ) .requireCsrfProtectionMatcher( new RequestMatcher() { public boolean matches(HttpServletRequest request) { // 仅对特定路径启用CSRF return request.getRequestURI().startsWith("/web/"); } }) .and() // API端点使用无状态认证 .authorizeRequests() .antMatchers("/api/**").authenticated() .and() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS); // API无状态 } }

验证 CSRF 是否生效

  1. 检查 Cookie:登录后查看浏览器是否有XSRF-TOKENCookie
  2. 测试请求
    • 直接发送 POST 请求应该被拒绝(403 错误)
    • 携带正确的 CSRF Token 的请求应该成功
  3. 检查响应头:某些配置下,响应头会包含 CSRF Token
# 使用 curl 测试 # 1. 先获取 CSRF Token(从登录后的 Cookie 或响应头) # 2. 发送带 CSRF Token 的请求 curl -X POST http://localhost:8080/api/test \ -H "Content-Type: application/json" \ -H "X-XSRF-TOKEN: YOUR_CSRF_TOKEN" \ -H "Cookie: XSRF-TOKEN=YOUR_CSRF_TOKEN" \ -d '{"data": "test"}'

总结:

禁用CSRF的前提条件:

  1. 应用不使用Cookie/Session进行身份认证
  2. 请求来源可控(如仅限移动App、内部服务)
  3. 已实施同等或更强的安全措施替代
http://www.cnnetsun.cn/news/1609949.html

相关文章:

  • OpenRocket模型火箭仿真软件:从设计到飞行的完整实践指南
  • OpenCore Legacy Patcher完整指南:四步让老旧Mac免费升级最新macOS
  • Shell脚本编程与自动化运维了解006
  • 在WS2812项目中实现高效RGB与HSV色彩空间转换
  • LibreOffice版本兼容性避坑指南:从7.6降级到7.3解决SfxBaseModel报错
  • Anomalib图像异常检测:用Patchcore模型快速验证工业质检数据集
  • 从DICOM到3D渲染:用ITK-SNAP快速上手医学影像分析与标注(附实战案例)
  • 全知视角与隐私边界的冲突
  • 如何让 OpenClaw等AI Agent 从“能用”走向“可控、可引导、可落地”
  • 别再瞎选TEC了!手把手教你读懂半导体制冷片性能曲线(以127对为例)
  • 告别单调表盘:Mi-Create如何让小米穿戴设备焕发个性光彩?
  • 单季暴增 132%!抓住短剧出海这3个信号!
  • 戴森球计划蓝图库:终极工厂自动化解决方案
  • 异地就医报销,为啥有人多有人少?
  • 大学生如何加入网络安全社团?发展建议
  • imgclsmob部署终极指南:从本地开发到生产环境的完整流程
  • 拯救数字青春:GetQzonehistory让QQ空间记忆永久安家
  • 提升协作效率:KityMinder云同步功能全链路应用指南
  • Nunchaku FLUX.1 CustomV3问题解决:提示词怎么写?参数怎么调?一篇搞定
  • AI大模型产品经理成长之路:从零基础到专家的详细学习路线全解析【AI大模型产品经理学习路线】
  • ssm+java2026年毕设体育队训练的信息管理系统【源码+论文】
  • 剑指offer-57、二叉树的下一个节点
  • 鸿蒙 HarmonyOS 6 | Video 组件网络视频播放异常排查实战
  • wifi相关查询指令
  • Omni-Vision Sanctuary 模拟电路设计可视化:与 Multisim 仿真结果结合生成原理图效果图
  • GD32F4/H7上移植FreeRTOS+YT8512驱动,从LAN8700例程到实战的保姆级避坑记录
  • Android Studio中文界面终极配置指南:快速告别英文开发困境
  • 深入解析J1939协议中的PDU报文格式与PGN计算
  • 零基础入门AI开发:在快马平台创建你的第一个对话skills智能体
  • 基于Phi-3-mini-128k-instruct构建运维智能助手:Linux命令分析与故障排查