11👍
You could probably subclass the CsrfViewMiddleware class and override the process_view method. Then include your custom middleware instead of the default CSRF one.
from django.middleware.csrf import CsrfViewMiddleware
class CustomCsrfMiddleware(CsrfViewMiddleware):
def process_view(self, request, callback, callback_args, callback_kwargs):
if request.META.get('api_key'):
# process api key
else:
return super(CsrfViewMiddleware, self).process_view(...)
6👍
You can use builtin csrf verification like this:
from django.middleware.csrf import CsrfViewMiddleware
def check_csrf(request):
reason = CsrfViewMiddleware().process_view(request, None, (), {})
if reason:
# CSRF failed
raise PermissionException() # do what you need to do here
5👍
I’ve been accessing the CsrfViewMiddleware
like Aldarund has shown but more needs to be said about this kind of solution:
-
If you are performing the test in a view, then you can return
reason
directly. According to how Django middleware works, whenprocess_view
returns something else thanNone
, then it must be aHttpResponse
object so it can just be returned by the view.There may be cases where you do not want to return
reason
directly, but if there is no reason not to do so, I’d rather return it, for consistency with how the site behaves in other cases. -
If you use the test in a run-of-the-mill view, and you already use
CsrfViewMiddleware
site-wide, it is usually the case thatrequest
will already have passed once throughCsrfViewMiddleware
. (Yes, it can happen. I have a case where a request I receive is modified and retested throughCsrfViewMiddleWare
after it has already been tested byCsrfViewMiddleware
due to the site-wide configuration.) However, the middleware setscsrf_processing_done
onrequest
after it tests it and won’t retest it if it is called again, because of this flag. Socsrf_processing_done
has to be reset toFalse
to perform a second test.
Here’s an illustration of the above:
from django.middleware.csrf import CsrfViewMiddleware
def view(request):
request.csrf_processing_done = False
reason = CsrfViewMiddleware().process_view(request, None, (), {})
if reason is not None:
return reason # Failed the test, stop here.
# process the request...
- Django – Multiple apps on one webpage?
- Django form with fields from two different models
- Django form with ManyToMany field with 500,000 objects times out
- Using APITestCase with django-rest-framework
- Django 'str' object is not callable
4👍
In my case, I wanted to POST some raw data with CSRF check.
So, I use this decorator requires_csrf_token in the view which process POST data :
from django.views.decorators.csrf import requires_csrf_token
@requires_csrf_token
def manage_trade_allocation_update(request):
In my template, I added csrf_token génération and put it in data post :
{% csrf_token %}
...
data['csrfmiddlewaretoken'] = document.querySelector('input[name="csrfmiddlewaretoken"]').value;
With this mecanism, I can use CSRF protection with manual HTTP POST request.
- Best way of linking to a page in Django
- Model limit_choices_to={'user': user}
- Django REST Framework: define fields in nested object?
- Django template rows of multiple items