`

改进django rest framework中的token验证,并加入cache

阅读更多

      在用户验证方面用到token验证,这是一种安卓/iso/..手机客户端常用的,方便的验证方式。

原理是客户端给我发一段字符串,这段字符串是用户在注册,登入的时候、服务器生成的,并关联到用户。保存到数据库,然后返回给客户端,客户端之后呢,就可以凭借这个字符串来确认“我是我,不是别人”。而不用每次验证都要通过账号密码。 _ _ _

django-rest-framework 有一套默认的token验证机制dfs token验证 具体用法不再细讲了,官方文档写得很清楚。

但是笔者发现一个问题,这个token验证机制存的token,一旦生成就保持不变。这样就引发一些问题,万一某人拿到你的token不就为所欲为了吗,就像别人拿到你的密码一样。

解决方案: 给token设置过期时间,超过存活时间,这段token不再具有验证功能,每次用户重新登入,刷新token(这段新token的有存活时间)。这样,重新登入后,你的token更新了,某些居心不良的人即便拿着之前抢来的token也没用。stackoverflow上已经有了token过期时间的讨论。 参考他们的代码我这样写。

##改进

#coding=utf-8   auth.py
from django.utils.translation import ugettext_lazy as _
from django.core.cache import cache

import datetime

from rest_framework.authentication import BaseAuthentication
from rest_framework import exceptions
from account.models import Token
from rest_framework import HTTP_HEADER_ENCODING

def get_authorization_header(request):
    """
    Return request's 'Authorization:' header, as a bytestring.

    Hide some test client ickyness where the header can be unicode.
    """
    auth = request.META.get('HTTP_AUTHORIZATION', b'')
    if isinstance(auth, type('')):
        # Work around django test client oddness
        auth = auth.encode(HTTP_HEADER_ENCODING)
    return auth

class ExpiringTokenAuthentication(BaseAuthentication):
    model = Token

    def authenticate(self, request):
        auth = get_authorization_header(request)

        if not auth:
            return None
        try:
            token = auth.decode()
        except UnicodeError:
            msg = _('Invalid token header. Token string should not contain invalid characters.')
            raise exceptions.AuthenticationFailed(msg)

        return self.authenticate_credentials(token)

    def authenticate_credentials(self, key):
        try:
            token = self.model.objects.get(key=key)
        except self.model.DoesNotExist:
            raise exceptions.AuthenticationFailed('认证失败')

        if not token.user.is_active:
            raise exceptions.AuthenticationFailed('用户被禁止')

        utc_now = datetime.datetime.utcnow()

        if token.created < utc_now - datetime.timedelta(hours=24 * 14):
            raise exceptions.AuthenticationFailed('认证信息过期')

    def authenticate_header(self, request):
        return 'Token'

还要配置settings文件

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'yourmodule.auth.ExpiringTokenAuthentication',
    ),
}

##再改进 使用了cache缓存对token和关联的用户进行了缓存,因为token验证经常需要从数据库读取,加入缓存,大幅提高速度。

def authenticate_credentials(self, key):
    
    token_cache = 'token_' + key
    cache_user = cache.get(token_cache)
    if cache_user:
        return cache_user     # 首先查看token是否在缓存中,若存在,直接返回用户

    try:
        token = self.model.objects.get(key=key)
    except self.model.DoesNotExist:
        raise exceptions.AuthenticationFailed('认证失败')

    if not token.user.is_active:
        raise exceptions.AuthenticationFailed('用户被禁止')

    utc_now = datetime.datetime.utcnow()

    if token.created < utc_now - datetime.timedelta(hours=24 * 14):  # 设定存活时间 14天
        raise exceptions.AuthenticationFailed('认证信息过期')

    if token:
        token_cache = 'token_' + key
        cache.set(token_cache, token.user, 24 * 7 * 60 * 60)  # 添加 token_xxx 到缓存

    return (token.user, token)

我的login函数是这样写的

@api_view(['POST'])
def login_views(request):
    receive = request.data   
    if request.method == 'POST':
        username = receive['username']
        password = receive['password']
        user = auth.authenticate(username=username, password=password)
        if user is not None and user.is_active:
            # update the token
            token = Token.objects.get(user=user)  
            token.delete()
            token = Token.objects.create(user=user)
            user_info = UserInfo.objects.get(user=user)
            serializer = UserInfoSerializer(user_info)

            response = serializer.data             
            response['token'] = token.key

            return json_response({
                "result": 1,
                "user_info":response, # response contain user_info and token 
                })
        else:
            try:
                User.objects.get(username=username)
                cause = u'密码错误'
            except User.DoesNotExist:
                cause = u'用户不存在'

            return json_response({
                "result": 0,
                "cause":cause,
                })

 

分享到:
评论

相关推荐

    Django REST framework讲义PDF全集,中文文档PDF版

    Django REST Framework(DRF)是基于Python的Django Web框架的一个强大扩展,专为构建Web API而设计。本讲义全面涵盖了这个框架的核心概念、功能以及最佳实践,旨在帮助开发者快速掌握如何利用DRF创建高效、可维护的...

    Vue+Django REST framework 打造生鲜电商项目.docx

    本项目的目标是使用 Vue 作为前端框架,Django REST framework 作为后端框架,设计并实现一个完整的生鲜电商项目。该项目将涵盖电商平台的主要功能,包括用户注册、登录、商品浏览、购物车管理、订单管理等。 2. ...

    django rest framework开发生鲜电商

    总结起来,"django rest framework开发生鲜电商"这个项目是利用Django REST framework强大的API构建能力,结合Vue.js的前端优势,来打造一个高效、用户友好的生鲜电商系统。通过理解并掌握这两个技术,开发者能够...

    Django REST framework 中文文档.pdf

    Django REST framework(DRF)是建立在Django Web框架之上的一款强大的、灵活的并且能够处理Web API的工具集。DRF为开发者提供了一套快速构建RESTful API的解决方案,它不仅能够帮助开发者避免重复的代码编写,还...

    Django-REST-framework教程中文版

    Django-REST-framework教程中文版是一份关于如何使用Django-REST-framework来快速创建REST风格API的中文教程。Django-REST-framework是一个建立在Django框架之上的强大的REST API工具包,它允许开发者利用Django的...

    django rest framework vue 实现用户登录详解

    在Django REST framework中实现用户登录,需要在Django的视图(views.py)中编写API接口,通常使用TokenAuthentication或SessionAuthentication这两种认证方式。 #### TokenAuthentication 使用TokenAuthentication...

    重写Django REST framework源码demo

    在本文中,我们将深入探讨如何重写Django REST framework(DRF)的源码来实现自定义功能。Django REST framework是一个强大的、灵活的用于构建Web API的工具包,它为Django项目提供了高效的序列化、认证、权限管理...

    Django rest framework中文

    Django REST framework(DRF)是一个强大的、灵活且易于使用的工具,旨在简化在Django项目中创建RESTful Web API的过程。接下来,我将详细介绍从零开始搭建一个Django REST framework中文教程所涉及的关键知识点。 ...

    Django restframework课件笔记详解

    Django REST framework(简称DRF)是Python Web开发领域中一个强大的工具,专门用于构建Web API。这个框架基于Django,提供了许多高级特性,使得开发者能够高效、灵活地构建高质量的RESTful API服务。本课件笔记将...

    django3.0+rest framework + Vue 生鲜超市项目-后端

    在本项目中,我们探索的是一个基于Django 3.0、Django Rest Framework和Vue.js构建的生鲜超市电子商务平台的后端实现。这个项目旨在提供一个完整的开发环境,供学习者深入理解如何将这些技术整合在一起,创建一个...

    django-rest-framework 官方文档

    Django REST Framework是一个强大的和灵活的工具包,它简化了在Django项目中构建Web API的过程。它提供了许多开箱即用的功能,如序列化、认证、权限管理、分页以及各种HTTP方法的视图。 2. **序列化** 序列化是将...

    重写 Django REST framework drf-api-logger 应用

    在Django REST Framework(DRF)中,`drf-api-logger`是一个非常有用的库,它可以帮助开发者记录API请求的日志,以便于监控、调试和分析应用的行为。然而,原始的`drf-api-logger`可能并不完全满足所有需求,比如在...

    【33】[全栈开发 ]Vue+Django REST framework 打造生鲜电商项目视频教程 .txt

    【33】[全栈开发 ]Vue+Django REST framework 打造生鲜电商项目视频教程 .txt t

    基于django restframework.zip

    4. 认证与授权:Django REST framework内置了多种认证和授权策略,如Basic Auth、Token Auth、Session Auth等,可以根据项目需求选择合适的方式确保API的安全性。 5. 权限控制:框架允许自定义权限类,以便根据用户...

    Python库 | django-rest-framework-social-oauth2-1.0.1.tar.gz

    `django-rest-framework-social-oauth2` 是一个基于 Django Rest Framework 的社交认证扩展库,主要用于实现 OAuth2 身份验证流程。这个库使得 Django 应用能够轻松地集成各种社交媒体登录服务,如 Facebook、Google...

    rest-framework生成token

    使用rest-framework在django中创建和认证token,用于在移动端来认证和用户,本文通过自己编写模型来实现根据用户来生成token,在请求头中添加Authentication来进行认证,保持登录状态。可以直接使用,编写过程可以...

    django rest framework

    **Django REST Framework详解** Django REST Framework(简称DRF)是基于Python的Django Web框架构建RESTful API的强大工具。它提供了一套完整的解决方案,包括序列化、身份验证、权限控制、分页以及Web视图,使得...

    基于Django框架,使用Django REST framework前后端分离技术搭建的网上图书商店.zip

    在Django REST framework中,可以通过Token认证、Session认证等多种方式进行用户验证。项目可能采用了这些机制之一,确保只有合法用户能访问和操作图书商店的资源。 7. 数据库模型: Django中的数据库模型定义了...

    django rest frame work中文电子参考文档

    通过阅读“Django REST framework教程中文版.pdf”,开发者可以深入了解这些概念,并学会如何在实际项目中应用它们。这份文档详细解释了每个组件的工作原理、配置方法和使用示例,对于初学者和经验丰富的开发者来说...

Global site tag (gtag.js) - Google Analytics