Spring Security CSRF防护与CORS配置实战指南
1. Spring Security中的CSRF防护机制解析CSRFCross-Site Request Forgery跨站请求伪造是Web应用中常见的安全威胁。Spring Security默认会对所有非安全HTTP方法如POST、PUT等启用CSRF防护。其核心原理是通过同步器令牌模式服务端生成唯一令牌CsrfToken令牌存储在会话或Cookie中客户端需在后续请求中携带该令牌服务端验证令牌有效性1.1 默认配置与工作原理Spring Security 6.x的默认CSRF配置包含以下关键组件Configuration EnableWebSecurity public class SecurityConfig { Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .csrf(Customizer.withDefaults()); // 启用默认CSRF防护 return http.build(); } }默认实现包含三个核心部分HttpSessionCsrfTokenRepository- 将令牌存储在HttpSession中XorCsrfTokenRequestAttributeHandler- 提供BREACH攻击防护CsrfFilter- 处理实际的令牌验证逻辑关键点从Spring Security 6开始CSRF令牌加载改为延迟模式只有需要验证的请求才会加载会话这显著提升了性能。1.2 令牌存储策略对比Spring Security提供两种主要的令牌存储方式存储方式实现类适用场景优点缺点Session存储HttpSessionCsrfTokenRepository传统Web应用安全性高需要会话支持Cookie存储CookieCsrfTokenRepositorySPA/前后端分离无状态需防范XSSCookie存储的典型配置http.csrf(csrf - csrf .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) );1.3 禁用CSRF防护的场景在某些API-only的应用中可能需要禁用CSRFhttp.csrf(csrf - csrf.disable());更精细的控制方式是指定忽略路径http.csrf(csrf - csrf .ignoringRequestMatchers(/api/public/**) );2. CORS跨域配置实战2.1 CORS与CSRF的关系虽然都涉及跨域安全但CORS和CSRF解决的是不同层面的问题CORS控制哪些外部域可以访问资源CSRF防止未授权的命令执行2.2 Spring Security中的CORS配置全局CORS配置示例Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config new CorsConfiguration(); config.setAllowedOrigins(List.of(https://trusted.com)); config.setAllowedMethods(List.of(GET,POST)); config.setAllowCredentials(true); UrlBasedCorsConfigurationSource source new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration(/**, config); return source; }与Spring Security集成http.cors(cors - cors .configurationSource(corsConfigurationSource()) );2.3 常见CORS错误处理遇到has been blocked by CORS policy错误时检查预检请求(OPTIONS)是否通过响应头是否包含Access-Control-Allow-Origin带凭证请求时是否设置allowCredentialstrue复杂请求是否声明了Access-Control-Allow-Methods3. Session管理高级配置3.1 会话固定保护Spring Security默认启用会话固定保护http.sessionManagement(session - session .sessionFixation().migrateSession() );可选策略changeSessionId仅更改IDServlet 3.1migrateSession创建新会话并复制属性默认newSession创建全新会话none禁用保护3.2 并发会话控制限制单个用户的会话数量http.sessionManagement(session - session .maximumSessions(1) .maxSessionsPreventsLogin(true) );3.3 会话超时处理结合CSRF时需特别注意Bean public HttpSessionEventPublisher httpSessionEventPublisher() { return new HttpSessionEventPublisher(); }配置会话失效URLhttp.sessionManagement(session - session .invalidSessionUrl(/session-expired) );4. 综合配置示例4.1 安全配置模板Configuration EnableWebSecurity public class SecurityConfig { Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .cors(cors - cors .configurationSource(corsConfigurationSource()) ) .csrf(csrf - csrf .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) .ignoringRequestMatchers(/api/public/**) ) .sessionManagement(session - session .sessionFixation().migrateSession() .maximumSessions(1) .expiredUrl(/session-expired) ); return http.build(); } Bean public CorsConfigurationSource corsConfigurationSource() { // 同上文CORS配置 } }4.2 测试配置要点测试CSRF防护的MockMvc示例Autowired private WebApplicationContext context; private MockMvc mockMvc; BeforeEach void setup() { mockMvc MockMvcBuilders .webAppContextSetup(context) .apply(springSecurity()) .build(); } Test void postWithValidCsrf() throws Exception { mockMvc.perform(post(/submit) .with(csrf())) // 自动添加有效CSRF令牌 .andExpect(status().isOk()); }5. 疑难问题排查指南5.1 CSRF相关错误问题1InvalidCsrfTokenException可能原因表单缺少_csrf参数AJAX请求未携带X-CSRF-TOKEN头会话超时导致令牌失效解决方案检查表单是否包含input typehidden name_csrf th:value${_csrf.token}/对于AJAX请求添加headers: {X-CSRF-TOKEN: token}问题2CookieCsrfTokenRepository不工作检查点是否设置了withHttpOnlyFalse()前端是否正确读取XSRF-TOKEN cookie是否在请求头中携带X-XSRF-TOKEN5.2 CORS相关错误问题预检请求失败典型表现Response to preflight request doesnt pass access control check解决方案确保OPTIONS请求不被拦截.requestMatchers(HttpMethod.OPTIONS).permitAll()检查CORS配置是否包含所需方法config.setAllowedMethods(List.of(GET,POST,PUT,DELETE,OPTIONS));5.3 Session相关错误问题session persistence异常现象重启后会话丢失集群环境下会话不同步解决方案配置持久化Session存储spring.session.store-typeredis添加依赖dependency groupIdorg.springframework.session/groupId artifactIdspring-session-data-redis/artifactId /dependency6. 性能优化建议CSRF令牌延迟加载Spring Security 6默认// 无需特别配置默认已启用会话优化减少会话中存储的数据量考虑使用session.statelesstrue的无状态架构CORS缓存config.setMaxAge(3600L); // 预检结果缓存1小时异步处理http.sessionManagement(session - session .sessionCreationPolicy(SessionCreationPolicy.ALWAYS) );实际项目中我曾遇到一个SPA应用因频繁预检请求导致性能下降的情况。通过调整CORS缓存时间和精简允许的方法列表最终将API响应时间降低了40%。关键配置如下config.setAllowedMethods(List.of(GET,POST)); // 仅允许必要方法 config.setMaxAge(7200L); // 预检缓存2小时

相关新闻

C++函数式编程三件套:Lambda、Bind与Function实战解析

C++函数式编程三件套:Lambda、Bind与Function实战解析

1. 项目概述:为什么我们需要这三个“神器”?如果你写过一段时间的C,尤其是从C11标准开始接触现代C,那你一定对lambda、bind和function这三个名字不陌生。它们经常被并称为C的“函数神器”或“函数三件套”。但很多开发者&#xff…

2026/10/1 3:01:47 阅读更多 →
Spring Boot 3.5整合MyBatis-Plus实战与优化指南

Spring Boot 3.5整合MyBatis-Plus实战与优化指南

1. 项目概述 Spring Boot 3.5与MyBatis-Plus的整合是当前Java企业级开发中最热门的技术组合之一。作为一名长期使用这套技术栈的开发者,我发现很多团队在整合过程中都会遇到相似的困惑和陷阱。本文将从一个实战者的角度,完整解析从环境搭建到生产部署的全…

2026/10/9 10:25:11 阅读更多 →
【LLM】一文讲透 AI Agent:从概念到四大核心组件

【LLM】一文讲透 AI Agent:从概念到四大核心组件

Agent 到底是什么? 这两年,“Agent” 无疑是 AI 领域最高频的词汇之一。很多人对它有一个模糊的认知,知道它比普通 AI 更强大,但真要准确定义,又往往说不清楚。 抛开晦涩的学术定义,我们可以用一个生活化的…

2026/10/9 20:09:21 阅读更多 →

最新新闻

Penpot 47000 星开源设计工具:用 MCP Server 打通 AI 设计工作流,TaoToken 统一 Key 接入实战

Penpot 47000 星开源设计工具:用 MCP Server 打通 AI 设计工作流,TaoToken 统一 Key 接入实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 21:49:38 阅读更多 →
桌面Agent如何重构数据分析师与产品经理的工作方式

桌面Agent如何重构数据分析师与产品经理的工作方式

1. 桌面Agent的进化,比预想中来得更猛上一轮桌面Agent刚火起来的时候,大家讨论最多的是“数据分析师会不会失业”。那会儿Agent能做的还只是帮忙跑个脚本、整理个表格、写个SQL,操作电脑桌面更像是演示环节里走个过场。我当时的判断是&#x…

2026/10/10 21:49:38 阅读更多 →
Matlab实现粒子群算法无功优化:IEEE14节点实战全解析

Matlab实现粒子群算法无功优化:IEEE14节点实战全解析

直接讲几句大实话:电力系统无功优化这个方向,论文里写了无数遍,但真正动手在Matlab里把一段能跑的代码调通、把粒子群算法和无功潮流耦合起来,中间的门槛远比看公式要高。我自己第一次做这个题目时,光是搞清楚控制变量…

2026/10/10 21:49:38 阅读更多 →
MFC 十六进制转十进制存 TXT:CString 格式化落盘实战与 TaoToken 辅助排错

MFC 十六进制转十进制存 TXT:CString 格式化落盘实战与 TaoToken 辅助排错

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 21:49:38 阅读更多 →
Android应用开发提高系列——Activity生命周期与TaoToken统一Key通道的调试实践

Android应用开发提高系列——Activity生命周期与TaoToken统一Key通道的调试实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 21:49:37 阅读更多 →
可视化运维监控实战:让故障可见、可控、可定位

可视化运维监控实战:让故障可见、可控、可定位

做运维的最怕什么?不是半夜被叫醒,而是被叫醒之后面对一墙壁的监控数据,却不知道线上到底哪里出了问题。过去几年我搭建过几套运维监控体系,从最早用开源的监控组件拼拼凑凑,到后来逐步落地可视化运维监控平台&#xf…

2026/10/10 21:48:37 阅读更多 →

日新闻

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

1. 从“卫星轨道分类”这个标题说起:为什么值得花时间搞懂第一次接触“卫星轨道分类”这个概念,很多人会觉得它离自己很远——不就是天上的星星怎么转吗?但如果你正在做航天任务规划、遥感数据接收、星座设计,甚至只是准备一场航天…

2026/10/10 0:00:39 阅读更多 →
Spring AOP 核心原理与实战:从概念到日志切面落地

Spring AOP 核心原理与实战:从概念到日志切面落地

1. 从一个真实痛点说起:为什么你的代码里到处都是重复逻辑刚入行那会儿,我写过一个用户管理模块,注册、登录、改密码、注销四个接口。每个接口里都塞了几乎一样的日志打印、参数校验、事务开启和提交。当时觉得没什么,能跑就行。直…

2026/10/10 0:00:40 阅读更多 →
Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

简介:这是一套面向计算机相关专业学生与项目实战学习者的Python数据采集与分析可视化完整项目,以Boss直聘岗位数据为对象,适合用作毕业设计、课程设计或期末大作业。资源包共38个文件,约246KB,以13个py源码文件为核心&…

2026/10/10 0:00:40 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 11:14:25 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 1:36:08 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 11:14:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 5:23:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →