Django Rest Framework的自定义Auth后端

时间:2015-05-19 09:24:33

标签: python django authentication django-rest-framework

我正在构建一个同时提供html和json api的应用程序。我正在使用自定义用户模型,需要一个自定义身份验证后端。

这是settings.py文件:

AUTHENTICATION_BACKENDS = ('tut.CustomAuthBackend.HybridAuth',)
AUTH_USER_MODEL = 'tutapp.User'

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'tutapp',
    'rest_framework'
)

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.security.SecurityMiddleware',
)

自定义用户模型是:

from django.db import models
from django.contrib.auth.models import AbstractBaseUser
from tut.CustomUserManager import CustomUserManager


class User(AbstractBaseUser):



    first_name = models.TextField(null=False)
    last_name = models.TextField(null=False)
    email = models.EmailField(null=False, unique=True)
    is_active = models.BooleanField(default=True)
    access_token = models.TextField(max_length=255, null=True)
    access_token_created_on = models.DateTimeField(null=True)
    is_admin = models.BooleanField(default=False)
    created_on = models.DateTimeField(auto_now_add=True)
    updated_on = models.DateTimeField(auto_now=True)

    objects = CustomUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name', 'last_name']

    def get_full_name(self):
        return self.first_name + " " + self.last_name

    def get_short_name(self):
        return self.first_name

    class Meta:
        ordering = ('created_on',)
        db_table = 'users'

网址:

from django.conf.urls import url
from rest_framework.urlpatterns import format_suffix_patterns
from tutapp import views
from django.conf.urls import include

urlpatterns = [url(r'^test/$',views.Test.as_view())]

urlpatterns = format_suffix_patterns(urlpatterns)


urlpatterns += [
    url(r'^api-auth/', include('rest_framework.urls',
                               namespace='rest_framework')),
]

我的自定义身份验证后端:

from tutapp.models import User
from django.conf import settings
from datetime import datetime, timedelta

class HybridAuth(object):

    def authenticate(self, email=None, password=None, token=None):



        try:
            if token:
                #Change this to check time validity of token
                last_month = datetime.today() - timedelta(days=settings.TOKEN_EXPIRY_DAYS)
                user = User.objects.filter(access_token=token, access_token_created_on__gte=last_month)
                if len(user) != 0:
                    return user[0]
                else:
                    raise ValueError('Token has expired')
            elif email and password:
                #Just a dumb implementation, will change it later
                user = User.objects.get(email=email, password=password)

            return user
        except:
             return None


    def get_user(self, user_id):
        try:
            return User.objects.get(id=user_id)
        except:
            return None

视图文件:

class Test(APIView):

    permission_classes = (permissions.IsAuthenticated,)

    def get(self, request, format=None):

        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets, many=True)
        if format == 'json':
            return Response(serializer.data)
        else:
            test = [ i for i in range(0,10)]
            return Response({'data' : test}, template_name='test.html')

我转到网址:http://127.0.0.1:8000/api-auth/login/但登录凭据似乎不起作用。当我使用标准django后端时,相同的凭据有效。不确定我做错了什么。

1 个答案:

答案 0 :(得分:0)

给下面一个镜头。我们的想法是返回用户或None,并且不会引发异常,以便在其中一个后端失败时可以使用其他后端。也使用User.check_password(password)。密码应存储为散列值,因此纯文本比较不起作用。

from tutapp.models import User
from django.conf import settings
from datetime import datetime, timedelta

class HybridAuth(object):
    def authenticate(self, email=None, password=None, token=None):
        if token:
            # Change this to check time validity of token
            last_month = datetime.today() - timedelta(days=settings.TOKEN_EXPIRY_DAYS)
            try:
                user = User.objects.filter(
                    access_token=token,  # This should be unique
                    access_token_created_on__gte=last_month,
                )[0]
            except IndexError:
                return None
        elif email and password:
            # Assumes that email is unique
            try:
                user = User.objects.get(email=email)

                # Utilizes User.check_password()
                if not user.check_password(password):
                    return None
            except User.DoesNotExist:
                return None
        else:
            return None

        return user


    def get_user(self, user_id):
        try:
            return User.objects.get(id=user_id)
        except:
            return None