Add CSRF token to all the FORM submissions
Asked Answered
B

1

1

I recently enabled CSRF protection in my web Application. There are around 100+ JSP pages containing FORM submission. What is the best way adding CSRF token :

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

such that all the form submission will have this form data. I don't want to add this parameter to every individual FORM submit.

Backsheesh answered 13/8, 2016 at 9:48 Comment(5)
maybe you want to use ajax?Shaum
I was about to ask the same question, I was also trying to create my own form tag but attributes are a bit complicated to include/pass to inner form. Next would be to override the form behavior when it's rendered. will keep you postedIsraelite
easiest way would be to use javascript to add this element to every formIsraelite
@TecHunter: partially reverted tag-edits. jsf and java-ee are not related at all to the original question... You can create a new specific question and answer it yourself or answer this questionKress
@Kress oh i mistook this question for a jsf question...Israelite
I
0

So I've finally found a working solution. Basically I create a custom FormRenderer like this :

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);
    }
}

Then register it to override the FormRenderer by setting it in faces-config.xml :

<?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>

I've tried to create a Component then add it as children but it wouldn't let me set the name of the input correctly so I directly write it.

Israelite answered 21/4, 2017 at 14:29 Comment(2)
Why do you need this? What problem does this solve that PrimeFaces does not already solve for you?Kress
I reverted your tag edits since you added tags (jsf e.g.) that were totally not related to the original question.Kress

© 2022 - 2024 — McMap. All rights reserved.