Django学习之Rest Framework 的Token验证功能优化详解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django学习之Rest Framework 的Token验证功能优化详解相关的知识,希望对你有一定的参考价值。

本文和大家分享的主要是django 中Rest Framework的Token相关内容,一起来看看吧,希望对大家 学习django有所帮助。
api 的通信采用 token + ssl ,简化和方便线上脚本的调用。 Django 版本 1.8.16 ,djangorestframework 版本 3.5.3 ,用了框架提供的 rest_framework.authtoken.views.obtain_auth_token 和rest_framework.authentication.TokenAuthentication 后,发现了一个问题,前者认证通过创建 token 后,这个 token 就不会自动更新了,非常不安全,非常危险。后者验证时候是不带缓存的,需要查询数据库,由于每次请求都要验证 token ,请求相当频繁,感觉不是很爽。
1 、实现生成的 token 带过期时间
首先在setting.py 配置文件设置过期时间  REST_FRAMEWORK_TOKEN_EXPIRE_MINUTES, 这里设置为 60 分钟
#REST_FRAMEWORK_TOKEN_EXPIRE_MINUTES = 60#
setting.py 同目录文件 view.py 编辑一个视图
##coding=utf8 import datetime from django.utils.timezone  import utc from django.conf import settings from rest_framework import status from rest_framework.response  import Responsefrom rest_framework.authtoken.models  import Token fromrest_framework.authtoken.views import ObtainAuthToken
EXPIRE_MINUTES = getattr(settings, ’REST_FRAMEWORK_TOKEN_EXPIRE_MINUTES’, 1)
 class  ObtainExpiringAuthToken(ObtainAuthToken):
 def  post(self, request):
serializer = self.serializer_class(data=request.data)
 if serializer.is_valid():
token, created =  Token.objects.get_or_create(user=serializer.validated_data[’user’])
utc_now = datetime.datetime.utcnow().replace(tzinfo=utc)
 if created  or token.created < utc_now - datetime.timedelta(minutes=EXPIRE_MINUTES):
token.delete()
token = Token.objects.create(user=serializer.validated_data[’user’])
token.created = utc_now
token.save()
 return Response({’token’: token.key})
 return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
obtain_expiring_auth_token = ObtainExpiringAuthToken.as_view()#
url.py 新增 url 用于生成用户 token
##from rest_framework.authtoken.views import obtain_auth_token from .views import obtain_expiring_auth_token
urlpatterns += [
#url(r’^api/token/’, obtain_auth_token, name=’api-token’),
url(r’^api/token/’, obtain_expiring_auth_token, name=’api-token’),
]#
用curl 测试接口  api/token/
#
git 优化Django&nbsp;Rest&nbsp;Framework&nbsp;的Token验证功能master) ? curl -H "Content-Type: application/json" -X POST -d ’{"username":"test","password":"test"}’ http://127.0.0.1:9000/api/token/
{"token":"6ff54785241f825846e4c5fca61cceb6be7f911e"}%#
然后,然后这个生成token 的接口就好了。目前还有一个问题,用户就是生成一个 token 例如 A ,然后用户再也不来请求这个接口生成 token ,那么这个用户的 token A 也会一直生效且不会被更新,那么要需要结合 token 验证函数,来强制删除用户过期的 token 。
2 、自定义 token 验证,强制删除过期的 token ,顺便缓存下没有过期的 token
首先在setting.py 文件新增全局认证类 api.authentication.ExpiringTokenAuthentication 替换默认的rest_framework.authentication.TokenAuthentication
#
REST_FRAMEWORK = {
’DEFAULT_AUTHENTICATION_CLASSES’: [
’rest_framework.authentication.BasicAuthentication’,
#’rest_framework.authentication.TokenAuthentication’,  #enable Token authentication
’api.authentication.ExpiringTokenAuthentication’
],
’PAGE_SIZE’: 10,
}#
新建authentication.py 文件,改文件在 api 这个目录下面。
# #coding=utf8 import datetime from django.utils.timezone  import utc from django.conf import settings fromrest_framework.authentication  import TokenAuthentication from rest_framework import exceptions from django.utils.translation import ugettext_lazy  as _
 from django.core.cache  import cache
EXPIRE_MINUTES = getattr(settings, ’REST_FRAMEWORK_TOKEN_EXPIRE_MINUTES’, 1)
 class  ExpiringTokenAuthentication(TokenAuthentication):
"""Set up token expired time"""
 def  authenticate_credentials(self, key):
# Search token in cache
cache_user = cache.get(key)
 if cache_user:
 return (cache_user, key)
model = self.get_model()
 try:
token = model.objects.select_related(’user’).get(key=key)
 except model.DoesNotExist:
 raise exceptions.AuthenticationFailed(_(’Invalid token.’))
 if  not token.user.is_active:
 raise exceptions.AuthenticationFailed(_(’User inactive or deleted.’))
utc_now = datetime.datetime.utcnow().replace(tzinfo=utc)
 if token.created < utc_now - datetime.timedelta(minutes=EXPIRE_MINUTES):
token.delete()
 raise exceptions.AuthenticationFailed(_(’Token has expired then delete.’))
 if token:
# Cache token
cache.set(key, token.user, EXPIRE_MINUTES * 60)
 return (token.user, token)#
来源: 小马

以上是关于Django学习之Rest Framework 的Token验证功能优化详解的主要内容,如果未能解决你的问题,请参考以下文章

Django-rest-framework 和 django-rest-framework-jwt APIViews and validation Authorization headers

Django Rest Framework 和 django Rest Framework simplejwt 两因素身份验证

怎么安装django rest framework

django rest framework中文介绍

MVC5 Entity Framework学习之Entity Framework高级功能

为啥 django-rest-framework 不显示 OneToOneField 数据 - django