I have attached two samples:
- jsf2token.war – sample UIToken component specifically for avoiding double submits (but would
probably handle CSRF attacks too)
- jsf2csrf.war – sample solution for handing Cross-site Request Forgery (CSRF) attacks only.
The source for both is in the WEB-INF/classes directory.
The token approach uses a standard JSF component that outputs a hidden field in the form. The hidden
field is created based on a server-generated secret key plus other information, such as the current view
id. What's a little different is that a phase listener decodes the component before Apply Request Values.
The goal here was to check the token before any other decoding takes place. Also, the token isn't
released until after Invoke Application to ensure that application processing has occurred.
For JSF 2, I think either enhancing UIForm, providing an alternate UIForm, or using a ClientBehavior
might be a better option than a separate component. Using UIForm would avoid the need to handle
decoding in the PhaseListener.
The CSRF approach is a little different. It still generates a special token based on a server-generated
secret key, but it does so based on the session, not on the view. It then appends the token to every JSF-
generated request through ViewHandler.getActionURL(). It uses a PhaseListener to ensure that every
incoming request has a valid token.
It's possible to combine these approaches, but I like the way the CSRF approach doesn't require anything
on the part of the developer. The caveat is that since it's session-based, it's probably not secure as a
form-based approach. Also, a form-based variant is required to avoid double-submits.
I'm not familiar with back button solutions, so I can't comment on how this code is applicable.