mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-05 04:50:12 +03:00
A solution to make csrf_exempt work for views
Summary of changes === 1. The ```Request``` class has a new attribute ```csrf_exempt``` (private attribute - ```_csrf_exempt```, property - ```csrf_exempt```) 2. A view class can define ```csrf_exempt = True``` if it needs to avoid CSRF checks. The default is ```False``` and it is passed to the ```Request``` class object creation in ```initialize_request``` which is stored as the attribute defined above 3. ```SessionAuthenticaton``` class' ```authenticate``` method performs ```enforce_csrf``` only if ```request.csrf_exempt``` is ```False``` What it effects? === Only ```SessionAuthentication``` where the default behavior is intact apart from the case where a user adds ```csrf_exempt = True``` in their view class, in which case the csrf checks are bypassed How to use? === Add the following to your view class: ```csrf_exempt = True``` Why this change? === Because ```SessionAuthentication``` is not aware of ```csrf_exempt``` when set through method decorators on a view class or its methods using a form like ```@method_decorator(csrf_exempt)``` or ```@method_decorator(csrf_exempt, name='dispatch')``` and hence CSRF checks cannot be bypassed even if these method decorators are in place.
This commit is contained in:
parent
e407dc7f01
commit
1bdb872bac
|
@ -125,6 +125,7 @@ class SessionAuthentication(BaseAuthentication):
|
||||||
if not user or not user.is_active:
|
if not user or not user.is_active:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if not request.csrf_exempt:
|
||||||
self.enforce_csrf(request)
|
self.enforce_csrf(request)
|
||||||
|
|
||||||
# CSRF passed with authenticated user
|
# CSRF passed with authenticated user
|
||||||
|
|
|
@ -81,7 +81,8 @@ def clone_request(request, method):
|
||||||
parsers=request.parsers,
|
parsers=request.parsers,
|
||||||
authenticators=request.authenticators,
|
authenticators=request.authenticators,
|
||||||
negotiator=request.negotiator,
|
negotiator=request.negotiator,
|
||||||
parser_context=request.parser_context)
|
parser_context=request.parser_context,
|
||||||
|
csrf_exempt=request.csrf_exempt)
|
||||||
ret._data = request._data
|
ret._data = request._data
|
||||||
ret._files = request._files
|
ret._files = request._files
|
||||||
ret._full_data = request._full_data
|
ret._full_data = request._full_data
|
||||||
|
@ -132,7 +133,7 @@ class Request(object):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, request, parsers=None, authenticators=None,
|
def __init__(self, request, parsers=None, authenticators=None,
|
||||||
negotiator=None, parser_context=None):
|
negotiator=None, parser_context=None, csrf_exempt=False):
|
||||||
self._request = request
|
self._request = request
|
||||||
self.parsers = parsers or ()
|
self.parsers = parsers or ()
|
||||||
self.authenticators = authenticators or ()
|
self.authenticators = authenticators or ()
|
||||||
|
@ -143,6 +144,7 @@ class Request(object):
|
||||||
self._full_data = Empty
|
self._full_data = Empty
|
||||||
self._content_type = Empty
|
self._content_type = Empty
|
||||||
self._stream = Empty
|
self._stream = Empty
|
||||||
|
self._csrf_exempt = csrf_exempt
|
||||||
|
|
||||||
if self.parser_context is None:
|
if self.parser_context is None:
|
||||||
self.parser_context = {}
|
self.parser_context = {}
|
||||||
|
@ -237,6 +239,13 @@ class Request(object):
|
||||||
self._authenticate()
|
self._authenticate()
|
||||||
return self._authenticator
|
return self._authenticator
|
||||||
|
|
||||||
|
@property
|
||||||
|
def csrf_exempt(self):
|
||||||
|
"""
|
||||||
|
Return the _csrf_exempt attribute
|
||||||
|
"""
|
||||||
|
return self._csrf_exempt
|
||||||
|
|
||||||
def _load_data_and_files(self):
|
def _load_data_and_files(self):
|
||||||
"""
|
"""
|
||||||
Parses the request content into `self.data`.
|
Parses the request content into `self.data`.
|
||||||
|
|
|
@ -358,12 +358,15 @@ class APIView(View):
|
||||||
"""
|
"""
|
||||||
parser_context = self.get_parser_context(request)
|
parser_context = self.get_parser_context(request)
|
||||||
|
|
||||||
|
csrf_exempt = getattr(self, 'csrf_exempt', False)
|
||||||
|
|
||||||
return Request(
|
return Request(
|
||||||
request,
|
request,
|
||||||
parsers=self.get_parsers(),
|
parsers=self.get_parsers(),
|
||||||
authenticators=self.get_authenticators(),
|
authenticators=self.get_authenticators(),
|
||||||
negotiator=self.get_content_negotiator(),
|
negotiator=self.get_content_negotiator(),
|
||||||
parser_context=parser_context
|
parser_context=parser_context,
|
||||||
|
csrf_exempt=csrf_exempt
|
||||||
)
|
)
|
||||||
|
|
||||||
def initial(self, request, *args, **kwargs):
|
def initial(self, request, *args, **kwargs):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user