如何在JSF-Spring集成应用程序中启用CSRF保护

我有一个JSF-Spring集成应用程序。 Spring安全性也集成在此应用程序中。 这些是我的应用程序中的版本:

  • JSF 2.2
  • Spring 4.0.3.RELEASE
  • Spring Security 3.2.4.RELEASE

根据JSF文档 ,JSF2.x [甚至旧版本]中的所有POST请求都将受CSRF保护。 但是我能够通过CSRF攻击来渗透我的应用程序。

我尝试了一个不同的JSF2.2仅[无Spring]示例应用程序,在这种情况下,我可以看到此示例应用程序受CSRF保护。

所以我的理解是,JSF / Spring / Spring安全组合在我的原始应用程序中给出了问题。 遗憾的是,日志文件中没有帮助信息。

我可以试试Spring Security CSRF保护 。 在这种情况下,挑战是我需要在所有POST情况下编辑代码。

我希望启用JSF CSRF保护,以避免此代码更改。 有什么建议吗?

我正在用Pinata进行测试。

使用Spring 4.3.7和Spring Security 4.2.2进行测试。

您需要为应用程序中的每个form添加CSRF令牌。 任何PATCH,POST,PUT和DELETE都将受Spring安全性保护(对于基本动词)。 为避免手动在每个表单中插入隐藏输入,您可以在提供的表单上创建FormRenderer:

 import com.sun.faces.renderkit.html_basic.FormRenderer; import javax.el.ELContext; import javax.el.ExpressionFactory; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import java.io.IOException; public class FormWithCSRFRenderer extends FormRenderer { @Override public void encodeEnd(FacesContext context, UIComponent component) throws IOException { log.debug("FormWithCSRFRenderer - Adding CSRF Token to form element"); ELContext elContext = context.getELContext(); ExpressionFactory expFactory = context.getApplication().getExpressionFactory(); ResponseWriter writer = context.getResponseWriter(); writer.startElement("input", component); writer.writeAttribute("type", "hidden", null); writer.writeAttribute("name", expFactory.createValueExpression(elContext, "${_csrf.parameterName}", String.class).getValue(elContext), null); writer.writeAttribute("value", expFactory.createValueExpression(elContext, "${_csrf.token}", String.class).getValue(elContext), null); writer.endElement("input"); writer.write("\n"); super.encodeEnd(context, component); } } 

然后通过在faces-config.xml设置它来注册它以覆盖FormRenderer:

     javax.faces.Form javax.faces.Form com.acme.FormWithCSRFRenderer    

另外,不要忘记在Spring环境中启用CSRF:

       

对于AJAX调用,您还需要在任何受保护的HTTP谓词的数据中添加此标记。 您可以直接从DOM检索令牌。