Explicit CSRF failure message. Fixes #60.

This commit is contained in:
Tom Christie 2012-10-15 14:03:36 +01:00
parent 9c1fba3483
commit 3c8f01b985
3 changed files with 25 additions and 10 deletions

View File

@ -4,6 +4,7 @@ Provides a set of pluggable authentication policies.
from django.contrib.auth import authenticate from django.contrib.auth import authenticate
from django.utils.encoding import smart_unicode, DjangoUnicodeDecodeError from django.utils.encoding import smart_unicode, DjangoUnicodeDecodeError
from rest_framework import exceptions
from rest_framework.compat import CsrfViewMiddleware from rest_framework.compat import CsrfViewMiddleware
from rest_framework.authtoken.models import Token from rest_framework.authtoken.models import Token
import base64 import base64
@ -71,12 +72,23 @@ class SessionAuthentication(BaseAuthentication):
http_request = request._request http_request = request._request
user = getattr(http_request, 'user', None) user = getattr(http_request, 'user', None)
if user and user.is_active: # Unauthenticated, CSRF validation not required
# Enforce CSRF validation for session based authentication. if not user or not user.is_active:
resp = CsrfViewMiddleware().process_view(http_request, None, (), {}) return
if resp is None: # csrf passed # Enforce CSRF validation for session based authentication.
return (user, None) class CSRFCheck(CsrfViewMiddleware):
def _reject(self, request, reason):
# Return the failure reason instead of an HttpResponse
return reason
reason = CSRFCheck().process_view(http_request, None, (), {})
if reason:
# CSRF failed, bail with explicit error message
raise exceptions.PermissionDenied('CSRF Failed: %s' % reason)
# CSRF passed with authenticated user
return (user, None)
class TokenAuthentication(BaseAuthentication): class TokenAuthentication(BaseAuthentication):

View File

@ -235,8 +235,11 @@ class BrowsableAPIRenderer(BaseRenderer):
return # Cannot use form overloading return # Cannot use form overloading
request = clone_request(request, method) request = clone_request(request, method)
if not view.has_permission(request): try:
return # Don't have permission if not view.has_permission(request):
return # Don't have permission
except:
return # Don't have permission and exception explicitly raise
if method == 'DELETE' or method == 'OPTIONS': if method == 'DELETE' or method == 'OPTIONS':
return True # Don't actually need to return a form return True # Don't actually need to return a form

View File

@ -156,14 +156,14 @@ class APIView(View):
""" """
raise exceptions.Throttled(wait) raise exceptions.Throttled(wait)
def get_parser_context(self, request): def get_parser_context(self, http_request):
""" """
Returns a dict that is passed through to Parser.parse_stream(), Returns a dict that is passed through to Parser.parse_stream(),
as the `parser_context` keyword argument. as the `parser_context` keyword argument.
""" """
return { return {
'upload_handlers': request.upload_handlers, 'upload_handlers': http_request.upload_handlers,
'meta': request.META, 'meta': http_request.META,
} }
def get_renderer_context(self): def get_renderer_context(self):