About two weeks back we released Jersey 1.9. See Jakub’s blog for more info on what’s new. One thing Jakub didn’t mention is that Jersey 1.9 also includes a new server side filter for Cross Site Request Forgery prevention. I won’t go into the details on what CSRF is – please refer to the OWASP CSRF page for that. Unfortunately, the generally recommended prevention is to generate per-request or per-session tokens on the server side, which client then has to include in its subsequent requests. This is quite easy to implement and there are servlet filters for doing that, however it does require a session state to be maintained and thus is not very RESTful. I was trying to implement something that would not require a session. After some searching I found the following two papers which both suggest there is a solution which works, and is not based on sessions:
- Guidelines for Implementation of REST from NSA
- Robust Defenses for Cross-Site Request Forgery from Standford University
The main idea is to check the presence of a custom header (agreed-upon between the server and a client – e.g. X-CSRF or X-Requested-By) in all state-changing requests coming from the client. The value of the header does not really matter. It works, because the browser would not send custom headers unless the web page makes a request using XMLHttpRequest, which only allows requests to the same site.
So, in Jersey 1.9 we added a server-side filter which does exactly that. You can find it here: server-side CsrfProtectionFilter.java
And, to make it easy to build clients, a corresponding client filter (that attaches the custom header to all potentially state-changing requests) is there as well: client-side CsrfProtectionFilter.
This can be further extended based on the feedback – we may add a check for the Referrer header and eventually even implement the session-based solution as an available configuration option. Just let us know, if you have an opinion.