Tomcat 7和CSRF过滤器

4
我正在尝试为JavaWeb应用程序添加CSRF保护。 我已经使用CSRF过滤器和过滤器映射到servlet对web.xml进行了配置。 但是,我不知道如何做下一步。文档说所有返回给客户端的URL都通过调用HttpServletResponse#encodeRedirectURL(String)或HttpServletResponse#encodeURL(String)进行编码。 他们还说你可以尝试: 或者,您可以将nonce作为名为org.apache.catalina.filters.CSRF_NONCE的请求参数传回,该请求参数的值为常量org.apache.catalina.filters.Constants.CSRF_NONCE_REQUEST_PARAM的值。
更新: 我仍然无法解决403禁止访问的问题。 有人有什么建议吗? 下面是web.xml的设置:
<filter>
    <filter-name>CSRF</filter-name>
    <filter-class>org.apache.catalina.filters.CsrfPreventionFilter</filter-class>
    <init-param>
      <param-name>entryPoints</param-name>
      <param-value>/html,/html/</param-value>
    </init-param>
  </filter>

  <filter-mapping>
    <filter-name>CSRF</filter-name>
    <servlet-name>exampleservlet</servlet-name>
  </filter-mapping>

以下是 JSP 页面的代码

<FORM METHOD="POST"  ACTION="<%=response.encodeURL("/exampleservlet")%>">
        <INPUT TYPE="HIDDEN" NAME="org.apache.catalina.filters.CSRF_NONCE" VALUE="<%=session.getAttribute("org.apache.catalina.filters.CSRF_NONCE")%>">
        <INPUT TYPE="HIDDEN" NAME="id" VALUE="0">

我做错了什么?

我们也遇到了同样的问题。有人找到解决方案吗? - Piyush Gupta
1个回答

5
我认为现在这个问题已经不再重要,因为它是多年前提出的,但我偶尔会访问它以获取对org.apache.catalina.filters.CsrfPreventionFilter使用的一些提示。正如来自Tomcat官方网站CSRF_Prevention_Filter文档所描述的那样,这个CsrfPreventionFilter被假定映射到“/*”,并使用名为“entryPoints”的init-param来保存URL。

提供一种从受保护应用程序导航回来的方法

我将尝试简单地解释CsrfPreventionFilter完成的工作:
  1. 首先,当客户端访问应用程序时,请求的URL必须由过滤器映射,并匹配其中一个entryPoints。这样,CsrfPreventionFilter可以生成一个新的nonce存储到会话中,并且包装响应,覆盖HttpServletResponse#encodeRedirectURL(String)HttpServletResponse#encodeURL(String),同时不阻止请求(通过返回403)
  2. 页面中的URL应该由HttpServletResponse#encodeRedirectURL(String)或HttpServletResponse#encodeURL(String)进行编码,就像您在表单操作中所做的那样。实际上,“编码”是为了追加一个请求参数名“org.apache.catalina.filters.CSRF_NONCE”,值为过滤器在第一步生成的nonce。
  3. 当客户端访问编码的页面中的URL时,CsrfPreventionFilter会检查请求是否有效--即nonce是否与当前会话中存储的某个nonce匹配(使用默认大小为5的LRUCache存储,可以通过init-param nonceCacheSize设置)。
因此,除非您声明的Servlet exampleservlet也映射到“/*”或“/html,/html/”,并且/html可以导致持有表单的页面,否则您的代码将无法工作。
因为您在以下响应中使用的

<FORM METHOD="POST" ACTION="<%=response.encodeURL("/exampleservlet")%>">

没有被CsrfPreventionFilter包装,不会添加nonce的魔力。
同样,也不是以下这个

<INPUT TYPE="HIDDEN" NAME="org.apache.catalina.filters.CSRF_NONCE" VALUE="<%=session.getAttribute("org.apache.catalina.filters.CSRF_NONCE")%>">

将会成功,因为会话属性"org.apache.catalina.filters.CSRF_NONCE"从未被过滤器设置。即使有一个属性,它保存的是LRUCache实例而不是nonce字符串。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接