Web服务器与API分离场景下CSRF Tokens的实现机制咨询
前后端分离场景下CSRF Token的落地实践(静态前端+Spring Boot API)
核心逻辑回顾
CSRF Token的核心是服务器为每个用户会话生成唯一随机值,前端在提交状态变更请求(POST/PUT/DELETE等)时携带该值,服务器通过验证值的有效性来确认请求是用户主动发起的,而非跨站伪造。
静态前端(Nginx/S3)+ Spring Boot API的具体实现流程
你不需要让Spring Boot生成并返回HTML,静态页面完全可以独立托管,以下是两种主流方案:
方案1:前端主动请求Token接口
- 步骤:
- 用户访问Nginx/S3上的静态HTML页面,页面加载完成后,前端JS发起一个无副作用的GET请求到Spring Boot的Token接口(比如
/api/csrf-token) - Spring Boot通过
CsrfTokenRepository生成Token,默认存储在HttpSession中;如果是前后端分离场景,推荐配置为存储在非HttpOnly的Cookie中(方便前端读取) - API返回Token(比如JSON格式:
{"token": "abc123-def456"}) - 前端拿到Token后,可将其存入页面隐藏表单字段(如
<input type="hidden" name="_csrf" value="abc123-def456">)或JS全局变量,后续提交请求时:- 若用表单提交:隐藏字段会自动随表单数据发送
- 若用AJAX请求:通过自定义请求头(如
X-XSRF-TOKEN)携带Token
- Spring Boot的CSRF过滤器会自动校验请求中携带的Token与服务器端存储的Token是否匹配
- 用户访问Nginx/S3上的静态HTML页面,页面加载完成后,前端JS发起一个无副作用的GET请求到Spring Boot的Token接口(比如
方案2:利用Cookie自动传递Token(更高效)
这是Spring Security针对前后端分离场景的优化方案:
- 在Spring Boot中配置:
@Override protected void configure(HttpSecurity http) throws Exception { http.csrf() .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()); } - 流程:
- 用户首次访问任意受Spring Security保护的API接口时,服务器会自动在响应头中设置
Set-Cookie: XSRF-TOKEN=abc123-def456; SameSite=Lax - 浏览器会自动保存该Cookie,后续访问静态页面时,只要域名符合Cookie规则,JS就能读取这个Cookie的值
- 前端AJAX请求时,将Cookie中的Token放入
X-XSRF-TOKEN请求头 - Spring Boot会自动校验请求头与Cookie中的Token一致性(不需要手动存储到Session)
- 用户首次访问任意受Spring Security保护的API接口时,服务器会自动在响应头中设置
为什么要把Token嵌入HTML?
嵌入HTML(隐藏表单字段)是针对传统纯HTML表单提交场景的解决方案:当用户提交没有JS参与的普通表单时,表单会自动携带隐藏字段的Token,后端可以直接通过表单参数验证。
而在前后端分离的单页应用中,更多用请求头传递Token,但两种方式都是有效的——嵌入HTML的意义在于兼容无JS的传统表单场景,确保所有状态变更请求都能被CSRF防护覆盖。
容易忽略的细节
- Token必须绑定用户会话:不能全局共用一个Token,Spring Security默认已实现每个会话生成独立Token的逻辑
- Cookie的SameSite属性:必须设置为
Strict或Lax,这是CSRF防护的基础,防止Cookie被跨站请求携带 - 跨域配置:如果静态前端和API域名不同,需在Spring Boot中配置CORS,允许携带Cookie和自定义请求头(
X-XSRF-TOKEN) - Token过期策略:Token的有效期建议与用户会话过期时间一致,避免无效Token导致请求失败
内容的提问来源于stack exchange,提问作者michaelwmason95
相关产品推荐
相关产品推荐

