文档章节

优化Django Rest Framework 的Token验证功能

健康的程序员
 健康的程序员
发布于 2017/07/21 17:25
字数 704
阅读 24
收藏 0
点赞 0
评论 0

优化Django Rest Framework 的Token验证功能

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.conf import settings

from rest_framework import status

from rest_framework.response import Response

from rest_framework.authtoken.models import Token

from rest_framework.authtoken.views import ObtainAuthToken

 

EXPIRE_MINUTES = getattr(settings, 'REST_FRAMEWORK_TOKEN_EXPIRE_MINUTES', 1)

 

class ObtainExpiringAuthToken(ObtainAuthToken):

    """Create user token"""

    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'])

 

            time_now = datetime.datetime.now()

 

            if created or token.created < time_now - datetime.timedelta(minutes=EXPIRE_MINUTES):

                # Update the created time of the token to keep it valid

                token.delete()

                token = Token.objects.create(user=serializer.validated_data['user'])

                token.created = time_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:(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.conf import settings

from rest_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.'))

 

        time_now = datetime.datetime.now()

 

        if token.created < time_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)

#

然后然后,所有的功能都实现了,删除用户过期的token和缓存token减少数据库查询。

 

验证:

curl -l -H "Content-type:application/json" -X POST -d '{"username":"admin","password":"hsand23!"}' http://127.0.0.1:8000/api/api-token-auth/

{

    "token":"1ad0f18bfff5a5066415773f695e8eda5ec449e8"

}

 

curl -X GET http://127.0.0.1:8000/api/ -H 'Authorization: Token 1ad0f18bfff5a5066415773f695e8eda5ec449e8'

{"users":"http://127.0.0.1:8000/api/users/","groups":"http://127.0.0.1:8000/api/groups/","items":"http://127.0.0.1:8000/api/items/"}

本文转载自:http://www.xiaomastack.com/2017/03/31/%E4%BC%98%E5%8C%96django-rest-framework-%E7%9A%84token%E9%AA%8

共有 人打赏支持
健康的程序员
粉丝 6
博文 106
码字总数 35551
作品 0
杭州
程序员
Objectwitter-C 0.9.1 释出,支持推特卡片式引用功能

六周前,Twitter 增加了对推文的卡片式引用 “Quoted Tweet”,该功能能够节省用户转发其他人的推文并添加自己的评论时的字数,同时还能提升所有使用 Twitter 相关产品的用户体验: 最近,T...

开源中国真理部部长 ⋅ 2015/05/29 ⋅ 1

Objectwitter-C dev-0.9.3 释出,增添上传原生视频功能

今年一月,Twitter 启动了在官方移动客户端上的原生视频上传功能,两周前,该公司又宣布向第三方开发者开放 Twitter 原生视频上传功能的 API: 本次 Objectwitter-C 更新,就是从上游合并了视...

开源中国真理部部长 ⋅ 2015/06/08 ⋅ 2

二步验证 token 生成小程序--MinaOTP

MinaOTP MinaOTP 是一款用来生成二步验证token的小程序,基于 RFC6238 实现,TOTP算法由实现。 小程序会安全地实时计算动态二步验证token,token的,,也很方便。 小程序码 截图 功能 * 计算...

lancegin ⋅ 2017/07/01 ⋅ 0

Twitter API 封装--Objectwitter-C

什么是 Objectwitter-C Objectwitter-C 是一款稳定,成熟,全面的 Twitter REST/Streaming API 的 Objective-C 封装,其封装了 Twitter 的全部公开 API。由 @开源中国真理部部长 基于 STTwit...

开源中国真理部部长 ⋅ 2015/05/24 ⋅ 1

第三方平台正式支持接入微信公众平台JS-SDK

  之前微信公众平台面向开发者开放微信内网页开发工具包,现在第三方平台也能正式支持接入微信公众平台JS-SDK了,第三方平台可以在获得公众号的授权后,通过JS-SDK帮助公众号开发和实现网页...

ytkahcom ⋅ 2015/02/05 ⋅ 0

Microsoft Enterprise Library 5.0 系列教程(六) Security Application Block

开发人员经常编写需要安全功能的应用程序。这些应用程序通常需要执行一系列不同的安全操作,而且它们还经常与不同的基础安全提供程序(如 Microsoft Active Directory 目录服务、授权管理器、...

老朱教授 ⋅ 2017/10/08 ⋅ 0

mvilplss/nature-framework

框架简介 nature-framework是一个以自由为理念,以易用,代码简洁,开发快速,功能强大,易扩展,低耦合为目标,适用于快速开发的轻量级MVC+ORM框架。无getter/setter方法,无xml配置,包括源...

mvilplss ⋅ 2017/01/13 ⋅ 0

网站自动登录功能的设计

网站的自动登录一直都是有利于提高用户体验的功能,如果设计不好,也非常容易泄漏用户的账户信息。 比较常见的功能实现方案是将用户的登录信息保存在浏览器的Cookie中。看到一些设计有缺陷的...

星空1221 ⋅ 2013/12/18 ⋅ 11

UCKeFu 2.5.0 发布,开放REST API,API支持多租户

UCKeFu v2.5.0 发布,UCKeFu 基于 JAVA 语言开发,是一个全渠道融合的客户支持服务平台,聚合企业内部多个客服渠道,帮助各种行业各种规模的企业建立完整客服体系。 通过将邮件、短信、电话语...

优客服多渠道客服系统 ⋅ 2017/06/12 ⋅ 1

ThinkPHP 表单令牌验证功能

令牌验证 ThinkPHP新版内置了表单令牌验证功能,可以有效防止表单的远程提交等安全防护。 表单令牌验证相关的配置参数有: 'TOKENON'=>true, // 是否开启令牌验证 'TOKENNAME'=>'hash', // ...

zyt_1978 ⋅ 2016/03/27 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

说说javascript中的那些专业名词

DOM(Document Object Model) 文档对象模型 BOM(Browser Object Model) 浏览器对象模型 ECMA(European Computer Manufacturer's Association) 欧洲计算机制造商协会 W3C(World Wide Web Conso......

hang1989 ⋅ 33分钟前 ⋅ 0

Bootstrap Wizard 多步表单控件

废话 有一块需求是 有多步表单 点击下一步时触发验证一个范围内的表单,点击上一步或取消,清空表单并返回第一步,点击最后一步提交整个表单的 就找到了这个插件,本来自己写了一个原生的 fo...

无极之岚 ⋅ 49分钟前 ⋅ 0

如何利用Spring Cloud构建起自我修复型分布式系统

利用Netflix所打造的组件及各类大家熟知的工具,我们完全可以顺利应对由微服务以及分布式计算所带来的技术挑战。 在过去一年当中,微服务已经成为软件架构领域一个炙手可热的新名词,而且我们...

harries ⋅ 今天 ⋅ 0

临近实习前的感想

再过两星期就要开始新的一段实习了,想想去年的这个时候也在实习,心中不免思绪万千,也一直想写对2017做个总结,但一直迟迟没有下笔。 2017年的春节,我就开始准备开学后找份实习。那时候就...

无精疯 ⋅ 今天 ⋅ 0

Spring AOP(面向切面编程)

Spring AOP概念: Spring AOP 可以劫持一个执行的方法,在方法执行之前或之后添加额外的功能。通常情况下,AOP把项目中需要在多处用到的功能,比如日志、安全和事物等集中到一个类中处理,而...

霍淇滨 ⋅ 今天 ⋅ 0

人工智能、机器学习、数据挖掘以及数据分析有什么联系?

人工智能是目前炙手可热的一个领域,所有的互联网公司以及各路大迦们纷纷表态人工智能将是下一个时代的革命性技术,可与互联网、移动互联网时代的变更相媲美;AlphaGo在围棋领域战胜人类最顶...

董黎明 ⋅ 今天 ⋅ 0

使用 vue-cli 搭建项目

vue-cli 是一个官方发布 vue.js 项目脚手架,使用 vue-cli 可以快速创建 vue 项目,GitHub地址是:https://github.com/vuejs/vue-cli 一、 安装 node.js 首先需要安装node环境,可以直接到中...

初学者的优化 ⋅ 今天 ⋅ 0

设计模式 之 享元模式

设计模式 之 享元模式 定义 使用共享技术来有效地支持大量细粒度对象的复用 关键点:防止类多次创建,造成内存溢出; 使用享元模式来将内部状态与外部状态进行分离,在循环创建对象的环境下,...

GMarshal ⋅ 今天 ⋅ 0

SpringBoot集成Druid的最简单的小示例

参考网页 https://blog.csdn.net/king_is_everyone/article/details/53098350 建立maven工程 Pom文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM......

karma123 ⋅ 今天 ⋅ 0

Java虚拟机基本结构的简单记忆

Java堆:一般是放置实例化的对象的地方,堆分新生代和老年代空间,不断未被回收的对象越老,被放入老年代空间。分配最大堆空间:-Xmx 分配初始堆空间:-Xms,分配新生代空间:-Xmn,新生代的大小一...

算法之名 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部