
本文介绍在不重构的前提下,为遗留 Struts2 应用快速集成 CSRF 防护的实践方案,重点利用框架内置的 token 和 tokenSession 拦截器,无需引入外部依赖或修改 Servlet 过滤器链。
本文介绍在不重构的前提下,为遗留 struts2 应用快速集成 csrf 防护的实践方案,重点利用框架内置的 `token` 和 `tokensession` 拦截器,无需引入外部依赖或修改 servlet 过滤器链。
Struts2 自 2.1 起便原生支持 CSRF 防御机制,其核心是通过 Token 拦截器(token 或 tokenSession) 实现“一次有效令牌”校验:服务端生成唯一 token 并嵌入表单(如隐藏域),用户提交时拦截器比对请求中 token 与会话中存储的 token 是否一致且未被重复使用。该方案轻量、兼容性强,特别适合无法升级框架版本的老旧系统。
✅ 推荐方案:启用 tokenSession 拦截器(推荐用于表单提交场景)
tokenSession 比基础 token 更健壮——它在校验失败时不会中断请求流程,而是将错误信息存入 ActionContext,允许开发者统一处理(如跳转至错误页或提示重试),避免因误刷新导致白屏。
步骤如下:
-
在
struts.xml中定义包含 tokenSession 的拦截器栈(推荐):立即学习“Java免费学习笔记(深入)”;
<interceptors> <interceptor-stack name="csrfStack"> <interceptor-ref name="defaultStack"/> <interceptor-ref name="tokenSession"/> </interceptor-stack> </interceptors>
-
为需防护的 Action 指定该拦截器栈:
<action name="submitOrder" class="com.example.OrderAction" method="execute"> <interceptor-ref name="csrfStack"/> <result name="success">/success.jsp</result> <result name="invalid.token">/error/csrf.jsp</result> <!-- 自定义错误视图 --> </action>
-
在 JSP 表单中添加
<token></token>标签(自动生成隐藏 token 字段):<s:form action="submitOrder"> <s:token/> <!-- 必须置于 form 内部 --> <s:textfield name="orderAmount" label="金额"/> <s:submit value="提交订单"/> </s:form>
⚠️ 注意事项:
<token></token>必须出现在<form></form>内,且每个表单仅能出现一次;- 若页面含多个独立表单,需为每个表单单独添加
<token></token>;tokenSession拦截器默认将 token 存于HttpSession,确保应用部署在支持 session 粘滞的集群环境中;- 不建议在 GET 请求(如链接跳转)中启用 token 校验,因其易被浏览器预加载或 Referer 泄露,应仅保护 POST/PUT/DELETE 等状态变更操作。
? 替代方案:token 拦截器(适用于简单场景)
若需严格拒绝非法重复提交(如银行转账),可改用 token 拦截器,它会在 token 无效时直接返回 invalid.token 结果,不执行 Action 方法。配置方式类似,仅将 tokenSession 替换为 token 即可。
✅ 验证与测试建议
- 手动复制表单请求并重复提交 → 应触发
invalid.token流程; - 使用浏览器开发者工具删除
_token隐藏字段后提交 → 同样应被拦截; - 检查响应头中是否包含
X-Struts-Token-Valid: true(非必需,但可用于调试)。
综上,Struts2 的 tokenSession 拦截器是保护老旧 Java Web 应用免受 CSRF 攻击最直接、低风险的方案。它深度集成于框架生命周期,无需侵入业务代码,也无需额外维护 token 生成/校验逻辑,是遗留系统安全加固的理想选择。


















