SpringBoot传统WEB应用开启CSRF的流程

 更新时间:2026年01月04日 08:48:03   作者:张占岭  
CSRF是一种Web安全漏洞,攻击者利用受害者合法会话诱使执行非本意操作,文章介绍了CSRF的攻击原理、适用禁用场景以及Spring Security和Django中的禁用示例,同时,对比了不同CSRF保护机制的工作原理和适用场景,感兴趣的朋友跟随小编一起看看吧

CSRF 是什么?

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

简单比喻:

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

CSRF攻击原理:

攻击流程:

  • 用户登录:用户登录正常的网站A(如银行网站),获得登录凭证(Cookie/Session)
  • 用户访问恶意网站:用户在同一个浏览器中访问了攻击者的网站B
  • 恶意请求:网站B通过隐藏表单、图片src、AJAX等方式,向网站A发送请求
  • 自动携带凭证:浏览器会自动携带网站A的Cookie
  • 网站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保护?

适用禁用场景:

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

# 移动App通过API访问后端
# 使用Token认证(JWT/OAuth),而不是Session
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

仅提供非状态改变的操作

GET /api/users          # 只读操作,通常不需要CSRF
POST /api/transfer      # 写操作,需要CSRF

微服务内部通信

# 服务间调用使用服务凭证,而不是用户会话
service-to-service: true

某些特殊框架/场景

// 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 是否生效

  • 检查 Cookie:登录后查看浏览器是否有 XSRF-TOKEN Cookie
  • 测试请求
    • 直接发送 POST 请求应该被拒绝(403 错误)
    • 携带正确的 CSRF Token 的请求应该成功
  • 检查响应头:某些配置下,响应头会包含 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的前提条件:

  • 应用不使用Cookie/Session进行身份认证
  • 请求来源可控(如仅限移动App、内部服务)
  • 已实施同等或更强的安全措施替代
  • 确认攻击面不会因此扩大

黄金法则:

如果用户通过浏览器访问你的网站,并且网站使用了Cookie/Session,那么永远不要禁用CSRF保护。只有在完全理解风险并有替代方案时,才考虑为API服务禁用CSRF。

到此这篇关于springboot~传统WEB应用开启CSRF的文章就介绍到这了,更多相关java多线程内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 浅谈mybatisPlus的Ipage分页和map参数的问题

    浅谈mybatisPlus的Ipage分页和map参数的问题

    这篇文章主要介绍了mybatisPlus的Ipage分页和map参数的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • 用JAVA实现一套背压机制

    用JAVA实现一套背压机制

    背压依我的理解来说,是指订阅者能和发布者交互,可以调节发布者发布数据的速率,解决把订阅者压垮的问题,这篇文章主要介绍了用JAVA自己实现一套背压机制,需要的朋友可以参考下
    2023-06-06
  • Java中数组的定义与使用详解

    Java中数组的定义与使用详解

    这篇文章主要给大家介绍了关于Java中数组的定义与使用的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-11-11
  • springboot 如何配置多个jndi数据源

    springboot 如何配置多个jndi数据源

    这篇文章主要介绍了springboot 如何配置多个jndi数据源的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • Feign调用全局异常处理解决方案

    Feign调用全局异常处理解决方案

    这篇文章主要介绍了Feign调用全局异常处理解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • 浅谈Java引用和Threadlocal的那些事

    浅谈Java引用和Threadlocal的那些事

    这篇文章主要介绍了Java引用和Threadlocal的那些事,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-03-03
  • 浅谈java反射和自定义注解的综合应用实例

    浅谈java反射和自定义注解的综合应用实例

    本篇文章主要介绍了java反射和自定义注解的综合应用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • mybatisPlus实现逻辑删除,自动生成创建时间和更新时间方式

    mybatisPlus实现逻辑删除,自动生成创建时间和更新时间方式

    MyBatisPlus框架中,通过@TableField(fill=FieldFill.INSERT)和@TableField(fill=FieldFill.UPDATE)注解可以实现在插入和更新时自动填充字段,比如创建时间和更新时间,使用@TableLogic注解标识逻辑删除字段
    2024-09-09
  • IntelliJ IDEA Java项目手动添加依赖 jar 包的方法(图解)

    IntelliJ IDEA Java项目手动添加依赖 jar 包的方法(图解)

    这篇文章主要介绍了IntelliJ IDEA Java项目手动添加依赖 jar 包,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04
  • Java实例精炼掌握语法

    Java实例精炼掌握语法

    本章节我们将为大家介绍 Java 实现几大基础问题,通过实例学习我们可以更快的掌握 Java 的应用,感兴趣的朋友来看看吧
    2022-04-04

最新评论