在 <protected-views> 中声明的视图在操作 CSRF 令牌后仍然可以访问

View declared in <protected-views> still accessible after manipulating CSRF token

我正在探索 JSF 2.2 中的新功能(到目前为止非常酷)但我仍然不明白受保护视图的工作原理,我创建了一个带有 link 到 facelet2 的 facelet1,如下所示:

<h:link styleClass="link" value="Go to protected page" id="link1"
    outcome="/protected/facelet2.xhtml"></h:link>

在我的脸上-config.xml我添加了这个:

<protected-views>
    <url-pattern>/protected/facelet2.xhtml</url-pattern>
</protected-views>

现在,当我 运行 页面中添加了一个标记 url:

http://localhost:8080/<project>/protected/facelet2.faces?javax.faces.Token=1426608965211

根据文档,如果令牌与服务器中的令牌不匹配,则不会处理 GET 请求(我的理解是否正确?)。

但是,如果我修改令牌(使用 Firebug 或浏览器中包含的开发工具),即使令牌已修改,请求仍会得到处理。

我是不是做错了什么?

这是因为您的 FacesServlet 显然映射到 *.faces 的 JSF 1.0 样式 URL 模式而不是 [= 的 JSF 2.0 样式 URL 模式15=]。 <protected-views><url-pattern> 必须与您在浏览器地址栏中看到的实际 URL 模式匹配。

因此,给定 /protected/facelet2.faces 的实际 URL,您需要按如下方式配置它:

<protected-views>
    <url-pattern>/protected/facelet2.faces</url-pattern>
</protected-views>

但是,我在当前的 Mojarra 2.2.10 实现中发现了一些讨厌的问题:

  1. 它实际上并没有根据 Servlet 12.1 规范进行 prefix/suffix 匹配 (there's even a vague comment in source code indicating that!)。它只是精确匹配。这意味着,您不能使用通配符 URL 模式,例如 /protected/*.

  2. 生成 <h:link> 时,它不会将受保护的视图 URL 模式与已解析的 URL 模式进行比较,而是将其与 JSF 视图 ID 进行比较。而且,在检查传入请求时,它不会将请求 URL 与 JSF 视图 ID 进行比较(就像在 link 生成期间一样),而是与 <url-pattern> 进行比较。因此,这永远不会匹配,完全解释了为什么您可以在没有有效令牌的情况下简单地访问它。

基本上,如果您需要保持 *.faces.

的 JSF 1.0 样式 URL 模式,则需要以下配置
<protected-views>
    <url-pattern>/protected/facelet2.xhtml</url-pattern>
    <url-pattern>/protected/facelet2.faces</url-pattern>
</protected-views>

在没有有效令牌的情况下访问时,它会正确地抛出 javax.faces.application.ProtectedViewException。更好的方法是将 FacesServlet 显式映射到 web.xml 中的 *.xhtml

<servlet-mapping>
    <servlet-name>facesServlet</servlet-name>
    <url-pattern>*.xhtml</url-pattern>
</servlet-mapping>

这样你就永远不需要处理虚拟 URLs。

我已将此事报告给 Mojarra 的 issue 3837

另请参阅:

  • Sometimes I see JSF URL is *.jsf, sometimes *.xhtml and sometimes /faces/*. Why?