Hi all, I'm thinking about 'championing' this thing, having just done a bit more work on the existing CsrfMiddleware [1], and I've done some more thinking about the different issues. LONG email, sorry, this is quite complex stuff.
== First == Simon suggested that the current middleware displays scary messages when people's sessions' expire, but that doesn't seem to be the case (normally). The middleware simply checks for a session cookie and corresponding token, and only if they don't match does it throws a nasty page back. The token itself does not expire, and even if the session has, the middleware doesn't know and doesn't care. The *only* way I have succeeded in getting to the scary "Cross Site Request Forgery detected" message is like this: - open a page that returns a POST form (either in a view that requires authentication or one that doesn't). - aquire a new session *in a different tab*. This might mean: 1) you had no session when you opened the first page, and you log in in a different tab. 2) you manually delete the session cookie, and do something that triggers a new sesssion 3) you are doing something in a different tab, your session expires by itself and you are given a new one. - in the first tab, try to submit the form. It fails because the token in the page disagrees with the new session cookie. Note that: - logging out and logging in in another tab is not enough (unless this causes a new session to be created). - waiting for the cookie to expire, or deleting the session from the database is not enough. In both these cases, you will be presented by the normal 'your session has expired' screen for views that require authentication, or you will simply carry on as normal if the view doesn't require authentication. The above cases that trigger the screen seem to be quite unusual - I've never seen it myself when actually using a site with the CsrfMiddleware installed. So what I'm saying is that the 'view protection' part of the middleware seems to work well enough for the vast majority of cases. If necessary we could always allow the error page to be customised via a setting (i.e. allow for a dotted path to a view function), and we could improve the default implementation to do something sensible, like display a message and then redirect to the original page after 5 seconds. I like the middleware for this part, because it means you are safe by default, and it works for any POST form -- no special action required. Note that the recent changes to this middleware allow you to selectively turn it off for chosen views using a decorator. == Second == There is the issue of how to insert a CSRF token into the forms. Two proposals: - SafeForm - this takes a request, so it can generate the required field, removing the need for the 'html munging' part of CsrfMiddleware. - it could also have a validate method that would remove the need for the 'view protection' part of CsrfMiddleware - If the developer is manually specifying each field in their forms rather than using form.as_table() etc, they will have to edit the template. - a template tag - it would require using django.core.context_processors.request - it would depend on the 'view protection' part of CsrfMiddleware - it would always require changing the template to insert this tag - the major advantage is that it can be used with any POST form, so that no matter how your form works, there is one way to sort out the CSRF problem - add a template tag (and ensure the middleware is on). == Third == There is the 'login CSRF' problem. One solution: - simply start a session whenever a login page is accessed if there is no session already, and then use the normal mechanism above. - There are some issues with this in terms of implementation [2] - bots that hit the login page will generate sessions. Second solution: - have a special 'login cookie' - a randomly generated id, not stored in the database, that is accompanied by a corresponding token. Requires some custom logic in every login view (you have to generate the cookie, add it to the response, and also tell the form/template about the value of the cookie/token). It may be possible to abstract some of this out into helper functions. Third solution: - Add the functionality of the second solution to SafeForm. It would require SafeForm to be able to set cookies and therefore to access the response, so the API gets a bit ugly. == Conclusion == At the moment, once you've factored everything in, I think 'view middleware' + template tag is the way to go, with some more custom solution for login CSRF. The SafeForm ends up having an unwieldly API, which means it won't be used or could be used incorrectly, it will often require changing a template anyway, and it's specific to Django forms. The template tag solution would basically require a single line being added to the template for each form (plus some settings, once). I also suggest we add CsrfMiddleware or CsrfViewMiddleware to the default middleware and put a note about it in the release notes. Regards, Luke == Notes == [1] http://code.djangoproject.com/changeset/9554 - automatic exceptions for AJAX - manual exceptions possible http://code.djangoproject.com/changeset/9553 - split middleware into two components. [2] It will mean: 1) always doing a redirect when you display a login form: you have to create a new session, send the session cookie with a HttpRedirectResponse, then in the next request create a form that has the csrf token in it. Decorators like @staff_member_required would need changing. OR 2) creating a new session and returning a form with a csrf token at the same time. The mechanism that generates the token will need to be aware that the session ID might not be in request.COOKIES[SESSION_COOKIE_NAME], but in request.session.?? -- "Outside of a dog, a book is a man's best friend... inside of a dog, it's too dark to read." Luke Plant || http://lukeplant.me.uk/ --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~----------~----~----~----~------~----~------~--~---