To enable the CSRF protection mechanism, set the following property to true
in
your CAE application (default is false
):
security.csrf-prevention.enabled=true
By enabling this feature, a random token will be stored in each non-anonymous user session. The client is expected to send the user's token value with every "unsafe" HTTP request (POST, PUT, DELETE). Any such "unsafe" request without a matching token will be treated as unauthorized and rejected.
Caution | |
---|---|
To be effective, the anti-CSRF token must be kept as secret as the HTTP session ID. |
In particular, mind the following:
A secure, random anti-CSRF token will be created for a user session, whenever a non-anonymous user authenticates with the application. The token value can be trusted for embedding in HTML attributes or text nodes without HTML escaping.
The token is made available as a model attribute
_CSRFToken
and can be used from a view.A hidden input field named
_CSRFToken
will be added automatically to any HTML form created using the Spring Form tag library. In future releases, this behavior may be changed to add the token only to forms with "unsafe" methods (such as POST).An interceptor will validate an anti-CSRF token sent with a request against the one stored in the user session. This validation only applies to "unsafe" request methods (POST, PUT, DELETE). If no request token is sent or the two token values do not match, an org.springframework.security.access.AccessDeniedException will be thrown. To support Ajax requests, the request token will be taken from the custom HTTP request header "X-CSRF-Token", if available. Otherwise, the request token will be taken from the request parameter
_CSRFToken
.
In order for this mostly transparent protection to work properly, an application must fulfill these simple requirements:
As recommended by RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1, the application must use "unsafe" HTTP methods (POST, PUT, DELETE) for any state-modifying HTTP requests.
Spring Security must be used for authentication.
The application must create a new HTTP session after successful authentication. This prerequisite is implemented by Spring Security's SessionFixationProtectionStrategy and is necessary to protect against session fixation attacks anyway.
Spring Security's AuthenticationTrustResolver is used to recognize anonymous users, so if an application implements custom Authentication objects to represent anonymous users, they should be compatible with the application's AuthenticationTrustResolver.
Spring's Form tag library should be used to create HTML forms, in order to add the anti-CSRF token automatically. Otherwise, forms to be sent via an unsafe HTTP method such as POST need to specify this field explicitly:
<input type="hidden" name="_CSRFToken" value="${_CSRFToken}"/>
Ajax XmlHttpRequests sent with an unsafe HTTP method such as POST, PUT, or DELETE, must include the token value: either as a
_CSRFToken
request parameter (when the request is built from form values, for instance) or as a custom request header "X-CSRF-Token". For instance, an application which makes heavy use of XmlHttpRequest via POST, could add the token value in a global HTML5 data attribute (or hidden form field or any other hidden DOM element):<html data-csrf-token="${_CSRFToken}"> ... </html>
When using jQuery, the token can be added to every POST Ajax request by registering an appropriate global
beforeSend
handler:$.ajaxSetup({ beforeSend: function ( xhr, settings ) { settings.headers["X-CSRF-Token"] = $("html").data("csrfToken"); } });
Example 4.17. Adding the anti-CSRF header to jQuery Ajax requests
The application should be prepared to handle the org.springframework.security.access.AccessDeniedException thrown by an interceptor, for instance by mapping it to an appropriate error code such as 403 (FORBIDDEN). See Section 4.3.9, “Dealing with Errors” for details.
Login CSRF prevention requires special treatment, because no (non-anonymous) user is authenticated when showing the login form.
To protect the login process, an application should force the creation of an anti-CSRF token
before rendering the login form by calling
com.coremedia.security.web.csrf.CsrfPreventionManagement#forceToken(HttpServletRequest).
The bean implementing this interface is available in a CAE application context as
csrfTokenManagement. Method
forceToken
has no effect, if no HTTP session exists or it already contains a
token, so the application must make sure that a session has been created before calling this
method.
Note that upon successful authentication, a new user session and a new token value will be created, as explained above.
If the login process is implemented as a Spring Webflow, the web flow framework will
typically take care of creating a HTTP session to manage web flow state. Since all
application context beans are available to expressions in a web flow definition, token
creation may be forced in the <on-entry>
phase of a
<view-state>
rendering the login form:
<on-entry> <evaluate expression="csrfTokenManagement.forceToken( flowRequestContext.externalContext.nativeRequest)"/> </on-entry>
Example 4.18. Forcing token creation from a login web flow