Customizing CSRF Protection In Spring Security

Starting in Spring Security 3.2, developers gained an easy solution to their Cross-Site Request Forgery problems with Spring’s implementation of the Synchronizer Token Pattern. Spring’s documentation does a great job of explaining Synchronizer Token Pattern and their implementation, so rather than talk about all of that, I’m going to show you how to tweak their configuration so you can have greater control over the urls that are protected.

Setup

Setting up CSRF protection in your application is easy. All you need to do is locate your existing Spring Security configuration and add the following snippet. This example is in XML, but it is just as simple to do with the Java configuration.

<http>
    <csrf/> <!--new stuff!-->
</http>

This setup can protect your whole app, as long as you are responsibly following HTTP method guidelines (use POST, GET, etc. appropriately). But what if you need to exclude a particular url?

Customization

In that case, you need to roll your own RequestMatcher. The RequestMatcher is a simple interface where you implement one method (matches) which takes an HttpServletRequest and returns a boolean. The boolean is just to tell Spring whether or not the request should have the CSRF token validated. You can then interrogate that request to your heart’s content to determine if you want Spring to do that validation. Here’s a simple example protects all your POST/DELETE/PUT requests, unless they are sent to “/unprotected”.

public class CsrfSecurityRequestMatcher implements RequestMatcher {
    private Pattern allowedMethods = Pattern.compile("^(GET|HEAD|TRACE|OPTIONS)$");
    private RegexRequestMatcher unprotectedMatcher = new RegexRequestMatcher("/unprotected", null);
 
    @Override
    public boolean matches(HttpServletRequest request) {
        if(allowedMethods.matcher(request.getMethod()).matches()){
            return false;
        }
 
        return !unprotectedMatcher.matches(request);
    }
}

To have Spring use this new configuration, you’ll need to let Spring manage an instance of your RequestMatcher, either by declaring it in a Spring XML context file or having Spring pick it up during a component scan. You can then wire it into your Spring Security configuration like this.

<http>
    <csrf request-matcher-ref="csrfSecurityRequestMatcher"/>
</http>

That’s all there is to it. If you’re interested in seeing a simple working app or how to test-drive your way into this code, take a look at our Customized Spring Security repository on GitHub.

2 comments

Comments are closed.