最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

django restframework使用redis實現(xiàn)token認(rèn)證

 更新時間:2021年09月22日 09:28:23   作者:曲鳥  
本文主要介紹了django restframework使用redis實現(xiàn)token認(rèn)證,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

一、前言

restframework有自己很方便的一套認(rèn)證、權(quán)限體系:官方文檔(tokenauthentication)

官方文檔的token 是基于數(shù)據(jù)庫中的authtoken_token表來做的

在這里插入圖片描述

有時候在后續(xù)接口中需要使用的用戶信息過多時,頻繁、高并發(fā)下的查詢數(shù)據(jù)庫會帶來比較大的性能消耗。這個時候我們就需要通過redis來做用戶認(rèn)證,并存儲一些用戶信息在其中。下面就為你講解如何基于redis來使用DRF做用戶認(rèn)證。

二、詳解

1. 前期準(zhǔn)備

1.1 安裝redis并啟動

自行安裝!這個都裝不好后面的教程也不用看了!看了也理解不了!

1.2 安裝django-redis庫

pip install django-redis -i https://pypi.tuna.tsinghua.edu.cn/simple

2. 配置redis

2.1 配置redis連接

settings.py輸入下面的代碼 (我的redis沒有設(shè)置密碼,所以配置代碼中無密碼相關(guān)配置)

# redis緩存配置
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "COMPRESSOR": "django_redis.compressors.zlib.ZlibCompressor",
            "IGNORE_EXCEPTIONS": True,
        }
    }
}

2.2 初始化redis連接

在項目初始化文件中(__init__.py)加入下面代碼進(jìn)行redis的初始化

在這里插入圖片描述

加入下列代碼

from django_redis import get_redis_connection
redis_connect = get_redis_connection()

3. 將token寫入redis

在之前的登錄接口是將token寫入數(shù)據(jù)庫的,現(xiàn)在需要重寫它讓其寫入redis

3.1 原來的登錄代碼

@api_view(['POST'])
def login(request):
    """
    登錄接口
    """
    user = authenticate(username=request.data['username'], password=request.data['password'])
    if user:
        Token.objects.filter(user_id=user.id).delete()
        token = Token.objects.create(user=user)
        _dict = {'id': user.id, 'username': user.username, 'first_name': user.first_name,
                 'last_name': user.last_name, 'email': user.email}        
        redis_connect.set(token.key, json.dumps(_dict), 259200)  # 存redis 259200秒=72個小時
        return Response(data={'status_code': 200, 'msg': '登錄成功!', 'token': token.key})
    return Response(data={'status_code': 403, 'msg': '密碼錯誤!'})

3.2 重寫后的登錄代碼

@api_view(['POST'])
def login(request):
    """
    登錄接口
    """
    user = authenticate(username=request.data['username'], password=request.data['password'])
    if user:
        token = binascii.hexlify(os.urandom(20)).decode()  # 生成token 的方式
        _dict = {'id': user.id, 'username': user.username, 'first_name': user.first_name,
                 'last_name': user.last_name, 'email': user.email}
        redis_connect.set(token, json.dumps(_dict), 259200)  # 存redis 259200秒=72個小時
        return Response(data={'status_code': 200, 'msg': '登錄成功!', 'token': token})
    return Response(data={'status_code': 403, 'msg': '密碼錯誤!'})

3.3 登錄后redis存儲的用戶記錄

在這里插入圖片描述

4. 重寫認(rèn)證token方法

4.1 源碼分析

我們可以全局搜索TokenAuthentication 找到【restframework】源碼中的Token認(rèn)證類

在這里插入圖片描述

這個類中我們只需要關(guān)注authenticate_credentials這個方法就可以了。

    def authenticate_credentials(self, 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.'))

        return (token.user, token)

源碼首先通過接口請求的token (源碼中的key) 去數(shù)據(jù)庫中尋找是否有該對應(yīng)的記錄
如果有則認(rèn)證成功返回usertoken這兩個模型對象

如果沒有對應(yīng)的記錄,則拋出【invalid token】異常

        try:
            token = model.objects.select_related('user').get(key=key)
        except model.DoesNotExist:
            raise exceptions.AuthenticationFailed(_('Invalid token.'))

如果有對應(yīng)的記錄,但用戶是未激活的 (is_active=0) 則拋出【User inactive or deleted】異常

      if not token.user.is_active:
            raise exceptions.AuthenticationFailed(_('User inactive or deleted.'))

然后restframework會在視圖層的dispatch方法中進(jìn)行異常的封裝并返回響應(yīng)結(jié)果。

4.2 進(jìn)行重寫

經(jīng)過源碼分析,我們需要重寫的有兩部分:

1.驗證token (源碼中的key) 是否有效,之前是從數(shù)據(jù)庫進(jìn)行驗證的現(xiàn)在需要通過redis去驗證

2.重新封裝user模型對象,但有個問題需要注意的是:
如果你重寫了django的user對象,讓它關(guān)聯(lián)了其他表的屬性,那么這里則不能將其封裝進(jìn)user這個對象的,因為redis不能存儲一個對象!,當(dāng)然如果非要這么做可以將外鍵id值在登錄 (寫入token) 的時候存入redis,然后在這里通過該外鍵id去查詢關(guān)聯(lián)的外鍵表獲取屬性,再封裝到user模型對象中!

重寫后的代碼

class RedisTokenAuthentication(TokenAuthentication):

    def authenticate_credentials(self, key):
        null = None  # json的None為null,所以需要定義一下
        user_data = redis_connect.get(key)
        if user_data:
            user_dict = json.loads(user_data)
            user_obj = User()
            for key_name in user_dict.keys():
                setattr(user_obj, key_name, user_dict[key_name])
            return user_obj, key
        raise exceptions.AuthenticationFailed(_('無效的token.'))

4.3 加入認(rèn)證配置

settings.py配置文件中,加入如下配置

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (  #如果有REST_FRAMEWORK配置項了單獨(dú)加入該項即可
        'Demo.RedisAuthentication.RedisTokenAuthentication',  # 項目名稱.重新認(rèn)證類所在的文件.類名
    ),
}

4.4 效果展示

增加一個接口

path('test-token', views.test_token),

接口方法代碼

@api_view(['GET'])
@permission_classes((permissions.IsAuthenticated,))
def test_token(request):
    """
    測試token
    """
    print('登錄的用戶名是:', request.user)
    res_data = {'data': {'status_code': 200}}
    return Response(**res_data)

輸出結(jié)果

登錄的用戶名是: admin

三、總結(jié)

無論是django還是restframework,他們的源碼和官方文檔在我看來是非常清晰的 (在我看的那么多官方文檔中算很清晰的了) 這里給DRF的團(tuán)隊點個贊??!!

到此這篇關(guān)于django restframework使用redis實現(xiàn)token認(rèn)證的文章就介紹到這了,更多相關(guān)django restframework token認(rèn)證內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • numpy中np.nditer、flags=[multi_index] 的用法說明

    numpy中np.nditer、flags=[multi_index] 的用法說明

    這篇文章主要介紹了numpy中np.nditer、flags=['multi_index'] 的用法說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05
  • 詳解Python下Flask-ApScheduler快速指南

    詳解Python下Flask-ApScheduler快速指南

    Flask是Python社區(qū)非常流行的一個Web開發(fā)框架,本文將嘗試將介紹APScheduler應(yīng)用于Flask之中,非常具有實用價值,需要的朋友可以參考下
    2018-11-11
  • NumPy庫中np.mean的具體使用

    NumPy庫中np.mean的具體使用

    np.mean?是 NumPy 庫中的一個函數(shù),用于計算給定數(shù)組或數(shù)組元素的算術(shù)平均值,本文主要介紹了NumPy庫中np.mean的具體使用,具有一定的參考價值,感興趣的可以了解一下
    2025-04-04
  • PySide6精簡教程(附圖文!)

    PySide6精簡教程(附圖文!)

    PySide6是Qt的Python封裝,是Qt for Python的組成之一,另一部分是Shiboken,下面這篇文章主要給大家介紹了關(guān)于PySide6精簡教程的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • 基于PyQt5制作一個表情包下載器

    基于PyQt5制作一個表情包下載器

    每次和朋友聊天苦于沒有表情包,而別人的表情包似乎是取之不盡、用之不竭。作為一個程序員哪能甘愿認(rèn)輸,所以本文將用Python制作一個表情包下載器供大家斗圖,需要的可以參考一下
    2022-03-03
  • Python-re中search()函數(shù)的用法詳解(查找ip)

    Python-re中search()函數(shù)的用法詳解(查找ip)

    這篇文章主要介紹了Python-re中search()函數(shù)的用法-----查找ip,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • wxPython中文教程入門實例

    wxPython中文教程入門實例

    這篇文章主要為大家分享下python編程中有關(guān)wxPython的中文教程,分享一些wxPython入門實例,有需要的朋友參考下
    2014-06-06
  • python框架django中結(jié)合vue進(jìn)行前后端分離

    python框架django中結(jié)合vue進(jìn)行前后端分離

    本篇將基于Python+Django結(jié)合Vue.js前端框架,為大家介紹如何基于這三者的技術(shù)棧來實現(xiàn)一個前端后離的Web開發(fā)項目。文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • 在Spyder中如何導(dǎo)入項目

    在Spyder中如何導(dǎo)入項目

    文章介紹了在Spyder中導(dǎo)入已存在項目時遇到的錯誤及解決方法,通過創(chuàng)建新項目并復(fù)制`.spyproject`文件夾到已存在項目中,可以成功導(dǎo)入項目,此外,還提到如何在Spyder中顯示項目資源管理器
    2025-01-01
  • 插入排序_Python與PHP的實現(xiàn)版(推薦)

    插入排序_Python與PHP的實現(xiàn)版(推薦)

    下面小編就為大家?guī)硪黄迦肱判騙Python與PHP的實現(xiàn)版(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05

最新評論

金堂县| 永顺县| 金湖县| 阿拉善右旗| 新郑市| 称多县| 佛教| 卫辉市| 永兴县| 凤山县| 迭部县| 鞍山市| 出国| 永年县| 镇雄县| 武强县| 新晃| 图木舒克市| 静安区| 抚远县| 漯河市| 苍南县| 林口县| 星子县| 光泽县| 岳西县| 兴城市| 元谋县| 泸定县| 长岛县| 和龙市| 互助| 浦北县| 阿城市| 万山特区| 镇远县| 纳雍县| 浦城县| 修文县| 饶河县| 凌云县|