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.

Kukeltje
  • 12,223
  • 4
  • 24
  • 47
Vivek
  • 152
  • 1
  • 4
  • 10
  • maybe you want to use ajax? – FreezY Aug 15 '16 at 02:20
  • 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 posted – TecHunter Apr 21 '17 at 09:40
  • easiest way would be to use javascript to add this element to every form – TecHunter Apr 21 '17 at 09:50
  • 1
    @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](https://stackoverflow.com/questions/26886121/how-to-enable-csrf-protection-in-jsf-spring-integrated-application?noredirect=1&lq=1) question – Kukeltje Apr 24 '17 at 10:56
  • @Kukeltje oh i mistook this question for a jsf question... – TecHunter Apr 24 '17 at 15:23

1 Answers1

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.

TecHunter
  • 6,091
  • 2
  • 30
  • 47
  • Why do you need this? What problem does this solve that PrimeFaces does not already solve for you? – Kukeltje Apr 24 '17 at 10:52
  • I reverted your tag edits since you added tags (jsf e.g.) that were totally not related to the original question. – Kukeltje Apr 24 '17 at 10:55