struts2 token 不仅能够有效防止表单重复提交,而且还可以进行
CSRF 验证。
CSRF 攻击原理如下图:
CSRF 攻击原理图
事实上,B 可能也是一个良性网站,只是被黑客 XSS 劫持了而已。用户实在冤枉啊:我没有上乱七八糟的网站,怎么还是中招了呢?
struts2 token 校验原理如图所示:
Struts2 token 验证原理图
对照 CSRF 攻击原理图,可以看到,虽然 a.jsp 将这个令牌值返回给浏览器,但是 B 是无法拿到这个令牌的具体值的,或者说 B 只能够通过去请求 A 才能拿到一个令牌,但这样就失去了伪造用户请求的目的,因为 session 不一致了。所以 b.action 也就不再处理这个伪造的请求,截断了 CSRF 的流程如下图所示:
Struts2 token截断了CSRF攻击原理图
了解了原理,那就干活吧。结果发现很多非 form 表单提交的请求都被成功拦截了,比如原有的 ajax 请求(js / jQuery / DWR)、页面的 href 请求都无法正常工作了——把这些请求的 action 的 token 验证去掉就能正常工作,但却这给黑客带来了可趁之机。
那么怎么样才可以让 form 表单之外的其他请求传递 struts2 token 呢?
我们继续来深入了解一下 struts2 token 验证的原理。
CSRF 攻击原理如下图:
CSRF 攻击原理图
事实上,B 可能也是一个良性网站,只是被黑客 XSS 劫持了而已。用户实在冤枉啊:我没有上乱七八糟的网站,怎么还是中招了呢?
struts2 token 校验原理如图所示:
Struts2 token 验证原理图
对照 CSRF 攻击原理图,可以看到,虽然 a.jsp 将这个令牌值返回给浏览器,但是 B 是无法拿到这个令牌的具体值的,或者说 B 只能够通过去请求 A 才能拿到一个令牌,但这样就失去了伪造用户请求的目的,因为 session 不一致了。所以 b.action 也就不再处理这个伪造的请求,截断了 CSRF 的流程如下图所示:
Struts2 token截断了CSRF攻击原理图
了解了原理,那就干活吧。结果发现很多非 form 表单提交的请求都被成功拦截了,比如原有的 ajax 请求(js / jQuery / DWR)、页面的 href 请求都无法正常工作了——把这些请求的 action 的 token 验证去掉就能正常工作,但却这给黑客带来了可趁之机。
那么怎么样才可以让 form 表单之外的其他请求传递 struts2 token 呢?
我们继续来深入了解一下 struts2 token 验证的原理。
以最新版的 2.3.20 为例。我们在 struts.xml 对某 action 加 <interceptor-ref name="token"></interceptor-ref> 标签,事实上是配置了 org.apache.struts2.interceptor.TokenInterceptor 拦截器。查看其 doIntercept 源码:
protected String doIntercept(ActionInvocation invocation) throws Exception { if (log.isDebugEnabled()) { log.debug("Intercepting invocation to check for valid transaction token."); } //see WW-2902: we need to use the real HttpSession here, as opposed to the map //that wraps the session, becaus