将CSRF令牌添加到所有FORM提交

时间:2016-08-13 09:48:04

标签: spring-security csrf csrf-protection

我最近在我的网络应用程序中启用了CSRF保护。大约有100多个包含FORM提交的JSP页面。添加CSRF令牌的最佳方式是什么:

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> 

这样所有表单提交都将具有此表单数据。我不想将此参数添加到每个单独的FORM提交。

1 个答案:

答案 0 :(得分:0)

所以我终于找到了一个有效的解决方案。基本上我创建一个这样的自定义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:

<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
              version="2.2">
    <render-kit>
        <renderer>
            <component-family>javax.faces.Form</component-family>
            <renderer-type>javax.faces.Form</renderer-type>
            <renderer-class>com.acme.FormWithCSRFRenderer</renderer-class>
        </renderer>
    </render-kit>
</faces-config>

我尝试创建一个Component然后将其添加为子项,但它不允许我正确设置输入的名称,所以我直接写它。