Search in this blog

Thursday, July 2, 2015

Spring Security 4.x CSRF Protection for Facelets

Spring Security 4.x has enabled CSRF protection by default, this is great in most cases, the token should be sent in every form submission, if you are using Spring MVC you will not have problems cause the token is included automatically in every form (if protection is enabled).

Using JavaServer Pages (without spring mvc) needs spring security taglibs in order to include the toke (manually), example for meta tag:
<sec:csrfMetaTags>

Using Facelets you will get in trouble, if you search, there is a way to integrate Spring Security with Facelets with the taglibs ported for Facelets but the csrf tags are not included, I wrote a taglib including tha above one for Facelets, I gonna describe the way to integrate it (is really easy).

1.- Create a file for the taglib definition, in my case "/WEB-INF/taglibs/alex.springsecurity.taglib.xml"

<?xml version="1.0"?>
<!DOCTYPE facelet-taglib PUBLIC
"-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
"http://java.sun.com/dtd/facelet-taglib_1_0.dtd">

<facelet-taglib xmlns="http://java.sun.com/xml/ns/javaee"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
                version="2.0">
    <namespace>http://www.huizaches.com/alex/spring-security-taglib</namespace>
    <tag>
        <tag-name>csrfMetaTags</tag-name>
        <component>
            <component-type>CsrfMetaTag</component-type>
        </component>
    </tag>
      
</facelet-taglib>


2.- Include the taglib as a context param in web.xml
 
    <!-- Spring Security Facelets Tag Library -->
    <context-param>
        <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
        <param-value>/WEB-INF/taglibs/alex.springsecurity.taglib.xml</param-value>
    </context-param>


3.- Create the source for handling the taglib (com.alex.spring.security.tags.CsrfMetaTag in my case)
 
package com.alex.spring.security.tags;

import java.io.IOException;
import javax.faces.component.FacesComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import org.springframework.security.web.csrf.CsrfToken;


@FacesComponent(value = "CsrfMetaTag")
public class CsrfMetaTag extends UIComponentBase {

    @Override
    public String getFamily() {
        return "csrfMetaTags";
    }

    @Override
    public void encodeBegin(FacesContext context) throws IOException {
        HttpServletRequest req = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
        CsrfToken token = (CsrfToken) req.getAttribute(CsrfToken.class.getName());
        if (token != null) {
            try {
                String s = handleToken(token);
                context.getResponseWriter().write(s);
            } catch (IOException e) {
                throw e;
            }
        }

    }

    public String handleToken(CsrfToken token) {
        return "<meta name=\"_csrf_parameter\" content=\"" + token.getParameterName()
                + "\" />" + "<meta name=\"_csrf_header\" content=\""
                + token.getHeaderName() + "\" />" + "<meta name=\"_csrf\" content=\""
                + token.getToken() + "\" />";
    }

}
 


4.- Include the namespace in your web file
 
      xmlns:csec="http://www.huizaches.com/alex/spring-security-taglib" 

5.- Put the taglib in the header (this is most for ajax requests)
 
      <csec:csrfMetaTags />
 
6.- Put this code inside every form you use.
      <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />


That's all, now every request should be working.
 
I hope this can be useful, thanks for reading and see you in the next post.
 

No comments:

Post a Comment

Leave me a comment