前不久参照官方文档https://docs.djangoproject.com/en/dev/topics/auth/#other-authentication-sources,采用自己添加的backend重写了authenticate方法。这种方法简单,且文档中也有详例。google、百度中搜索亦有文档。
今天研究了如何使用token来进行authenticate,中文基本无相关文档,英文示例也寥寥无几,因此将今日成果记录于此,以往日后遗忘。今日工作主要参考以下文档:
http://stackoverflow.com/questions/5023762/token-based-authentication-in-django
http://djangosnippets.org/snippets/2313/
https://github.com/jpulgarin/django-tokenapi
其中的主要实现参考于tokenapi
在官方文档https://docs.djangoproject.com/en/dev/topics/auth/#writing-an-authentication-backend中,对token验证仅有一句话加一段声明。
But it could also authenticate a token, like so:
class MyBackend:
def authenticate(self, token=None):
# Check the token and return a User.
基于token的认证,主要是依赖于django.contrib.auth.tokens中的make_token和check_token,我首先在我的app中创建了TokenBackend.py,在其中重写authenticate函数:
from django.contrib.auth.models import User
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.tokens import default_token_generator
class TokenBackend(ModelBackend):
def authenticate(self, pk, token = None):
try:
user = User.objects.get(pk=pk)
except User.DoesNotExist:
return None
if default_token_generator.check_token(user, token):
return user
return None
并且在project中的setting.py中,要将AUTHENTICATION_BACKENDS设置为(其中
(
'
'django.contrib.auth.backends.ModelBackend',
)
此时,系统在调用authenticate时就会按照AUTHENTICATION_BACKENDS列表的顺序,依次使用相应的Backend来进行验证,倘若前者返回None,再调用下一条列表,否则完成验证。
然后,我在view中完成了函数token_new来创建Token,来记录用户的登录。
from django.contrib.auth import authenticate
from django.contrib.auth.tokens import default_token_generator
def token_new(request, localusername):
if request.method == 'POST':
if 'username' in request.POST and 'password' in request.POST:
user = authenticate(username = localusername, password = '')
if user:
data = {
'success': True,
'token': default_token_generator.make_token(user),
'user': user.pk,
}
return data
else:
return HttpResponse("Error token!")
elif request.method == 'GET':
if 'username' in request.GET and 'password' in request.GET:
user = authenticate(username = localusername, password = '')
if user:
data = {
'success': True,
'token': default_token_generator.make_token(user),
'user': user.pk,
}
return data
else:
return HttpResponse("Error token!")
from .http import JSONResponse, JSONError
if user:
......
return JSONResponse(data)
else:
return JSONError("Unable to log you in, please try again")
from django.http import HttpResponse
try:
import simplejson as json
except ImportError:
import json
# JSON helper functions
def JSONResponse(data, dump=True):
return HttpResponse(
json.dumps(data) if dump else data,
mimetype='application/json',
)
def JSONError(error_string):
data = {
'success': False,
'errors': error_string,
}
return JSONResponse(data)
token_data = token_new(request, localusername)
if 'token' in token_data:
user = authenticate(pk = token_data['user'], token = token_data['token'] )
return HttpResponse(user.username)
此外,按照tokenapi的启示,不必拘泥于django.contrib.auth.tokens中的方法,可以重写default_token_generator方法,达到特定的需求。比如在make_token的实现在django中如下:
def make_token(self, user):
"""
Returns a token that can be used once to do a password reset
for the given user.
"""
return self._make_token_with_timestamp(user, self._num_days(self._today()))
如有新进展和勘误,将会及时更新说明。