
本文介绍如何利用 struts2 内置的 token 和 tokensession 拦截器,为遗留 java web 应用快速、安全地集成 csrf 防御机制,无需重构核心逻辑,兼容性高且配置简洁。
本文介绍如何利用 struts2 内置的 token 和 tokensession 拦截器,为遗留 java web 应用快速、安全地集成 csrf 防御机制,无需重构核心逻辑,兼容性高且配置简洁。
Struts2 自 2.1 起即提供了成熟的 CSRF 防护支持,核心依赖于 token 和 tokenSession 两个内置拦截器。相较于手动编写过滤器(如 Filter 层面拦截),直接使用框架原生拦截器更可靠、更轻量,也避免了会话状态管理、令牌生命周期控制等常见实现陷阱。
✅ 推荐方案:启用 token 拦截器(推荐用于表单提交)
-
在 Action 配置中声明拦截器栈(
struts.xml):<action name="submitOrder" class="com.example.OrderAction" method="execute"> <interceptor-ref name="token"/> <interceptor-ref name="defaultStack"/> <result name="success">/success.jsp</result> <result name="invalid.token">/error/csrf.jsp</result> </action>
-
在 JSP 表单中插入隐藏令牌字段(自动由
<token></token>标签生成):<s:form action="submitOrder"> <s:token/> <!-- 关键:生成并提交唯一 token --> <s:textfield name="itemName" label="Item"/> <s:submit value="Submit"/> </s:form>
⚠️ 注意:
<token></token>必须置于<form></form>内部,且每个需防护的表单都应包含该标签;Struts2 会在服务端校验请求中struts.token参数与当前会话中存储的令牌是否匹配。立即学习“Java免费学习笔记(深入)”;
? 进阶选择:tokenSession 拦截器(防重复提交 + 更强会话绑定)
若还需防止用户误多次点击提交(如支付场景),可改用 tokenSession 拦截器:
<interceptor-ref name="tokenSession"/>
它在验证通过后自动清除令牌,使同一令牌仅能成功使用一次,且令牌与 HttpSession 强绑定,进一步降低令牌泄露后的滥用风险。
? 必须处理的返回结果
无论选用哪种拦截器,务必在 struts.xml 中显式声明 invalid.token 结果映射,否则校验失败时将抛出 InvalidTokenException 导致 500 错误:
<global-results>
<result name="invalid.token">/WEB-INF/jsp/csrf-error.jsp</result>
</global-results>? 注意事项与最佳实践
-
不建议在 Filter 层自行实现 CSRF 防护:Struts2 的拦截器已深度集成到 Action 生命周期,能准确识别合法表单请求、处理重定向/转发场景,并自动管理令牌生命周期;自定义 Filter 易绕过或与 Struts2 的
Preparable、ModelDriven等特性冲突。 -
AJAX 请求需额外处理:若前端通过 JS 提交(如
fetch或axios),需从页面 DOM 或 meta 标签中读取<token></token>渲染出的隐藏字段值,并作为请求头(如X-CSRF-Token)或参数传递;后端可通过自定义拦截器提取并委托给TokenInterceptor校验。 -
确保 Session 可用:
token拦截器依赖HttpSession存储令牌,确认应用未禁用 session(如session="false"在 JSP 中)。 -
升级建议(长期):Struts2 2.5.x+ 已默认启用
token相关拦截器增强机制,若应用版本低于 2.3.x,建议优先升级至受支持的 LTS 版本以获取安全补丁。
通过以上配置,老旧 Struts2 应用可在数小时内完成 CSRF 防护加固,零业务代码修改,兼顾安全性与可维护性。


















