django-rest-framework/djangorestframework/authentication.py

85 lines
3.6 KiB
Python
Raw Normal View History

"""The :mod:`authentication` modules provides for pluggable authentication behaviour.
2011-02-19 16:12:35 +03:00
2011-05-04 12:21:17 +04:00
Authentication behaviour is provided by adding the mixin class :class:`AuthenticatorMixin` to a :class:`.BaseView` or Django :class:`View` class.
2011-02-19 16:12:35 +03:00
The set of authentication which are use is then specified by setting the :attr:`authentication` attribute on the class, and listing a set of authentication classes.
2011-02-19 16:12:35 +03:00
"""
2011-01-24 21:59:23 +03:00
from django.contrib.auth import authenticate
from django.middleware.csrf import CsrfViewMiddleware
from djangorestframework.utils import as_tuple
2011-01-24 21:59:23 +03:00
import base64
2011-01-24 21:59:23 +03:00
class BaseAuthenticator(object):
"""All authentication should extend BaseAuthenticator."""
2011-01-24 21:59:23 +03:00
def __init__(self, view):
"""Initialise the authentication with the mixin instance as state,
in case the authentication needs to access any metadata on the mixin object."""
self.view = view
2011-01-24 21:59:23 +03:00
def authenticate(self, request):
"""Authenticate the request and return the authentication context or None.
An authentication context might be something as simple as a User object, or it might
be some more complicated token, for example authentication tokens which are signed
against a particular set of permissions for a given user, over a given timeframe.
2011-05-04 12:21:17 +04:00
The default permission checking on View will use the allowed_methods attribute
2011-01-24 21:59:23 +03:00
for permissions if the authentication context is not None, and use anon_allowed_methods otherwise.
2011-05-04 12:21:17 +04:00
The authentication context is available to the method calls eg View.get(request)
by accessing self.auth in order to allow them to apply any more fine grained permission
checking at the point the response is being generated.
2011-01-24 21:59:23 +03:00
This function must be overridden to be implemented."""
return None
class BasicAuthenticator(BaseAuthenticator):
"""Use HTTP Basic authentication"""
def authenticate(self, request):
from django.utils.encoding import smart_unicode, DjangoUnicodeDecodeError
2011-01-24 21:59:23 +03:00
if 'HTTP_AUTHORIZATION' in request.META:
auth = request.META['HTTP_AUTHORIZATION'].split()
if len(auth) == 2 and auth[0].lower() == "basic":
try:
auth_parts = base64.b64decode(auth[1]).partition(':')
except TypeError:
return None
try:
uname, passwd = smart_unicode(auth_parts[0]), smart_unicode(auth_parts[2])
except DjangoUnicodeDecodeError:
return None
2011-01-24 21:59:23 +03:00
user = authenticate(username=uname, password=passwd)
if user is not None and user.is_active:
return user
return None
class UserLoggedInAuthenticator(BaseAuthenticator):
"""Use Django's built-in request session for authentication."""
2011-01-24 21:59:23 +03:00
def authenticate(self, request):
if getattr(request, 'user', None) and request.user.is_active:
# If this is a POST request we enforce CSRF validation.
if request.method.upper() == 'POST':
# Temporarily replace request.POST with .RAW_CONTENT,
# so that we use our more generic request parsing
2011-04-27 21:44:21 +04:00
request._post = self.view.RAW_CONTENT
resp = CsrfViewMiddleware().process_view(request, None, (), {})
del(request._post)
if resp is not None: # csrf failed
return None
return request.user
2011-01-24 21:59:23 +03:00
return None
#class DigestAuthentication(BaseAuthentication):
# pass
#
#class OAuthAuthentication(BaseAuthentication):
# pass