#15518 closed New feature (fixed)
Separate CSRF checks to function
Reported by: | Vlastimil Zíma | Owned by: | nobody |
---|---|---|---|
Component: | Documentation | Version: | 1.2 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
I have troubles with enabling CSRF check in some of my views because there is no function that would return True/False or raised an exception.
My situation is like this:
I have 2 views, one that is protected by CSRF and other one is not. Both views calls same rendering function which renders a form that leads to protected view.
Problem is when first request ends at unprotected view, I have no CSRF_COOKIE in request.META and csrf_token template tag did not rendered one, so rendering returns a form that will always return CSRF reject page.
Change History (8)
comment:1 by , 14 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
comment:2 by , 14 years ago
Resolution: | invalid |
---|---|
Status: | closed → reopened |
I understand the problem, and it is a valid ticket. There is already a solution - django.views.decorators.csrf.requires_csrf_token
However, this function is not documented, and therefore 'doesn't exist yet'. Once documented, I'll close this ticket.
comment:3 by , 14 years ago
Component: | Core framework → Documentation |
---|---|
Triage Stage: | Unreviewed → Accepted |
comment:4 by , 14 years ago
That is what I needed, but still there is no common way how to call CSRF check, if you want to do it manually.
Code for view with CSRF check not provided by middleware/decorator looks
from django.middleware.csrf import CsrfViewMiddleware, _get_new_csrf_key, _sanitize_token from django.views.decorators.csrf import csrf_view_exempt @csrf_view_exempt def some_view(request): if (...some_conditions...): result = CsrfViewMiddleware().process_view(request, lambda: None, None, None) # if None is returned, than it is OK if result: # Store data back to session to prevent their loss return result return ...some other response...
We have view like this at endpoint for OpenID provider, but I do not like the way I have to call CSRF check.
comment:5 by , 14 years ago
An alternative way to do this is to split your view function into several views, or into a closures, and decorate with @csrf_protect:
@csrf_view_exempt def some_view(request): # Any setup here, including vars that may be referenced in path_1 or path_2 @requires_csrf_token def path_1(request): # ... @csrf_protect def path_2(request): # ... if (...some_condition...): return path_1(request) else: return path_2(request)
This seems like a reasonable solution to me, especially for something which is very definitely an edge case. If you have things that you need to do instead of immediately returning the 403 failure view, you can:
- subclass
CsrfViewMiddleware
- override the
_reject
method - make your own version of
csrf_protect
usingdecorator_from_middleware
.
This suggests we should make _reject
public by calling it reject
.
comment:6 by , 14 years ago
Severity: | → Normal |
---|---|
Type: | → New feature |
It's not at all clear to me what you are asking for here. I suspect the root of the problem is a misunderstanding about how to use the CSRF protection, as it's perfectly possible to have some views that are CSRF protected and others that are not. I suggest you ask on #django IRC or post a more complete description of your code to django-users for help.