Spring应用中CSRF Token未绑定用户上下文的安全问题咨询
解决Spring Security中CSRF Token未绑定用户上下文的漏洞
你遇到的这个问题是严重的CSRF风险——生成的CSRF Token没有和用户的会话上下文绑定,导致不同用户(或不同会话)的Token可以跨会话复用,攻击者能利用这个漏洞伪造请求篡改其他用户的操作。下面是具体的分析和修复方案:
问题本质
正常情况下,CSRF Token应该是每个用户会话独有的,这样才能确保请求确实来自当前用户的合法会话。但你的应用现在允许任意会话的Token通过验证,说明Token的存储或校验逻辑没有和用户Session做关联,比如:
- 错误地使用了全局共享的Token存储(比如未按Session隔离的缓存)
- 自定义的
CsrfTokenRepository实现逻辑错误,没有将Token与当前Session绑定 - 配置中意外禁用了Session关联的Token校验逻辑
修复方案
1. 确保使用Session绑定的CSRF Token存储
Spring Security默认的HttpSessionCsrfTokenRepository会将Token存储在当前用户的HttpSession中,每个Session对应唯一的Token,这是最安全的默认实现。如果你的配置中自定义了Token存储,改回默认实现即可:
@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http // 启用CSRF保护,并使用Session绑定的Token存储 .csrf(csrf -> csrf .csrfTokenRepository(new HttpSessionCsrfTokenRepository()) ) // 其他配置... .authorizeHttpRequests(auth -> auth .anyRequest().authenticated() ); return http.build(); } }
2. 校验Token与当前Session的关联性
如果必须自定义CsrfTokenRepository,一定要在实现中确保:
- 生成Token时,将其与当前请求的Session ID绑定存储
- 校验Token时,先从当前Session中取出对应的Token,再和请求携带的Token做严格比对,不匹配则直接拒绝请求
3. 强化会话安全配置
为了进一步降低风险,启用Session固定保护,确保用户登录时Session ID会被重新生成,避免攻击者利用旧Session的Token:
http .sessionManagement(session -> session .sessionFixation().migrateSession() // 登录时迁移Session,生成新的Session ID );
4. 验证修复效果
修复后,用以下方式测试:
- 打开两个独立的隐私窗口,分别登录不同用户(或同一用户的不同会话)
- 获取每个会话的CSRF Token(比如从页面隐藏域或响应头)
- 尝试用会话A的Token提交会话B的请求,确认请求会被Spring Security拒绝,这样就说明Token已经和用户上下文绑定成功了。
内容的提问来源于stack exchange,提问作者flooose
相关产品推荐
相关产品推荐

