找回密码
 立即注册
首页 业界区 安全 springboot~传统WEB应用开启CSRF

springboot~传统WEB应用开启CSRF

狭宁 昨天 13:10
CSRF 是什么?

CSRF(Cross-Site Request Forgery,跨站请求伪造) 是一种常见的Web安全漏洞。攻击者利用受害者已经登录的合法会话,诱使受害者执行非本意的操作。
简单比喻:

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

攻击流程:


  • 用户登录:用户登录正常的网站A(如银行网站),获得登录凭证(Cookie/Session)
  • 用户访问恶意网站:用户在同一个浏览器中访问了攻击者的网站B
  • 恶意请求:网站B通过隐藏表单、图片src、AJAX等方式,向网站A发送请求
  • 自动携带凭证:浏览器会自动携带网站A的Cookie
  • 网站A执行请求:网站A看到合法Cookie,误以为是用户的自愿操作
攻击示例:
  1. <img src="https://your-bank.com/transfer?to=hacker&amount=10000" width="0" height="0" />
  2. <form action="https://your-bank.com/change-email" method="POST">
  3.   <input type="hidden" name="email" value="hacker@evil.com">
  4. </form>
复制代码
为什么有时要禁用CSRF保护?

适用禁用场景:


  • 纯API服务(无浏览器交互)
    1. # 移动App通过API访问后端
    2. # 使用Token认证(JWT/OAuth),而不是Session
    3. Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
    复制代码
  • 仅提供非状态改变的操作
    1. GET /api/users          # 只读操作,通常不需要CSRF
    2. POST /api/transfer      # 写操作,需要CSRF
    复制代码
  • 微服务内部通信
    1. # 服务间调用使用服务凭证,而不是用户会话
    2. service-to-service: true
    复制代码
  • 某些特殊框架/场景
    1. // GraphQL通常使用token而不是session
    2. // 或某些实时通信应用
    复制代码
具体框架中的禁用示例:

Spring Security:
  1. @Configuration
  2. @EnableWebSecurity
  3. public class SecurityConfig extends WebSecurityConfigurerAdapter {
  4.     @Override
  5.     protected void configure(HttpSecurity http) throws Exception {
  6.         http
  7.             .csrf().disable()  // 禁用CSRF
  8.             .authorizeRequests()
  9.             .anyRequest().authenticated()
  10.             .and()
  11.             .httpBasic();  // 使用HTTP Basic认证
  12.     }
  13. }
复制代码
Django:
  1. # settings.py
  2. CSRF_COOKIE_SECURE = False  # 禁用CSRF
  3. # 或针对特定视图
  4. from django.views.decorators.csrf import csrf_exempt
  5. @csrf_exempt
  6. def api_view(request):
  7.     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. # 替代方案示例:
  2. 1. JWT Token认证:
  3.    每次请求携带: Authorization: Bearer <token>
  4.    
  5. 2. API Key + Secret:
  6.    请求签名: X-Signature: sha256(api_secret + request_data)
  7.    
  8. 3. OAuth 2.0:
  9.    使用Access Token进行授权
  10.    
  11. 4. CORS限制:
  12.    Access-Control-Allow-Origin: https://trusted-domain.com
  13.    
  14. 5. Rate Limiting:
  15.    限制请求频率防止滥用
复制代码
最佳实践建议:
  1. // 在Spring中,可以针对不同端点配置不同的CSRF策略
  2. public class SecurityConfig {
  3.     protected void configure(HttpSecurity http) {
  4.         http
  5.             // 对Web页面启用CSRF
  6.             .csrf(csrf -> csrf
  7.                 .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
  8.                 .csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler())
  9.             )
  10.                 .requireCsrfProtectionMatcher(
  11.                     new RequestMatcher() {
  12.                         public boolean matches(HttpServletRequest request) {
  13.                             // 仅对特定路径启用CSRF
  14.                             return request.getRequestURI().startsWith("/web/");
  15.                         }
  16.                     })
  17.             .and()
  18.             // API端点使用无状态认证
  19.             .authorizeRequests()
  20.                 .antMatchers("/api/**").authenticated()
  21.                 .and()
  22.             .sessionManagement()
  23.                 .sessionCreationPolicy(SessionCreationPolicy.STATELESS); // API无状态
  24.     }
  25. }
复制代码
验证 CSRF 是否生效


  • 检查 Cookie:登录后查看浏览器是否有 XSRF-TOKEN Cookie
  • 测试请求

    • 直接发送 POST 请求应该被拒绝(403 错误)
    • 携带正确的 CSRF Token 的请求应该成功

  • 检查响应头:某些配置下,响应头会包含 CSRF Token
  1. # 使用 curl 测试
  2. # 1. 先获取 CSRF Token(从登录后的 Cookie 或响应头)
  3. # 2. 发送带 CSRF Token 的请求
  4. curl -X POST http://localhost:8080/api/test \
  5.   -H "Content-Type: application/json" \
  6.   -H "X-XSRF-TOKEN: YOUR_CSRF_TOKEN" \
  7.   -H "Cookie: XSRF-TOKEN=YOUR_CSRF_TOKEN" \
  8.   -d '{"data": "test"}'
复制代码
总结:

禁用CSRF的前提条件:

  • 应用不使用Cookie/Session进行身份认证
  • 请求来源可控(如仅限移动App、内部服务)
  • 已实施同等或更强的安全措施替代
  • 确认攻击面不会因此扩大
黄金法则:
如果用户通过浏览器访问你的网站,并且网站使用了Cookie/Session,那么永远不要禁用CSRF保护。只有在完全理解风险并有替代方案时,才考虑为API服务禁用CSRF。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册