There are several techniques, which when used together provide a sufficient CSRF protection.
Unique Token
A single, session-specific token is good enough for most applications. Just make sure that your site doesn't have any XSS vulnerabilities, otherwise any kind of token technique you employ is a waste.
AJAX call to regenerate the token is a bad idea. Who will guard the guards? If the AJAX call itself is vulnerable to CSRF, it kind of defeats the purpose. Multiple tokens with AJAX are in general bad idea. It forces you to serialize your requests i.e. only one AJAX request is allowed at a time. If you are willing to live with that limitation, you can perhaps piggyback token for the second AJAX call in response to the first request.
Personally, I think it is better to re-authenticate the user for critical transactions, and protect the remaining transactions with the session-specific token.
Custom HTTP header
You can add a custom HTTP header to each of your requests, and check its presence on the server side. The actual key/value doesn't need to be secret, the server just needs to ensure it exists in the incoming request.
This approach is good enough to protect CSRF in newer versions of the browsers, however its possible too work-around this if your user has older version for Flash Player.
Checking Referrer
Checking for the Referrer header is also good to protect CSRF in the newer browsers. Its not possible to spoof this header, though it was possible in older versions of Flash. So, while it is not foolproof, it still adds some protection.
Solving Captcha
Forcing the user to solve a captcha is also effective against CSRF. Its inconvenient as hell, but pretty effective. This is perhaps the only CSRF protection that works even if you have XSS vulnerabilities.
Summary
- Use a session based token, but re-authenticate for high value transactions
- Add a custom http header, and also check for referrer. Both are not foolproof by themselves, but don't hurt
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…