我正在构建一个同时提供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后端时,相同的凭据有效。不确定我做错了什么。
答案 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