一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語(yǔ)言編程技術(shù)及教程分享平臺(tái)!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Python - django restframework使用redis實(shí)現(xiàn)token認(rèn)證

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

2022-01-10 00:06曲鳥 Python

本文主要介紹了django restframework使用redis實(shí)現(xiàn)token認(rèn)證,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

 

一、前言

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

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

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

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

 

二、詳解

 

1. 前期準(zhǔn)備

1.1 安裝redis并啟動(dòng)

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

1.2 安裝django-redis庫(kù)

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

 

2. 配置redis

2.1 配置redis連接

settings.py輸入下面的代碼 (我的redis沒有設(shè)置密碼,所以配置代碼中無(wú)密碼相關(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連接

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

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

加入下列代碼

from django_redis import get_redis_connection
redis_connect = get_redis_connection()

 

3. 將token寫入redis

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

 

3.1 原來(lái)的登錄代碼

@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個(gè)小時(shí)
        return Response(data={"status_code": 200, "msg": "登錄成功!", "token": token.key})
    return Response(data={"status_code": 403, "msg": "密碼錯(cuò)誤!"})

 

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個(gè)小時(shí)
        return Response(data={"status_code": 200, "msg": "登錄成功!", "token": token})
    return Response(data={"status_code": 403, "msg": "密碼錯(cuò)誤!"})

 

3.3 登錄后redis存儲(chǔ)的用戶記錄

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

 

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

 

4.1 源碼分析

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

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

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

    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)

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

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

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

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

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

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

 

4.2 進(jìn)行重寫

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

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

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

重寫后的代碼

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(_("無(wú)效的token."))

 

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

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

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

 

4.4 效果展示

增加一個(gè)接口

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

接口方法代碼

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

輸出結(jié)果

登錄的用戶名是: admin

 

三、總結(jié)

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

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

原文鏈接:https://blog.csdn.net/momoda118/article/details/120270428

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 99精品国产久热在线观看66 | kisssis无减删全集在线观看 | 高清在线一区二区 | 精品国产自在现线久久 | 免费看日本 | 日本加勒比无码av | 日比免费视频 | 99视频全部看免费观 | coolgay男男gayxxx chinese壮直男gay老年人 chinese野外gay军人 | 日本成年片高清在线观看 | 青青草精品 | 99热这里只有精品一区二区三区 | x8x8在线永久免费观看 | 日本视频免费看 | 精品国产一区二区三区久久久狼 | 男女一级特黄a大片 | 免费国产网站 | 亚洲国产欧美在线人成aaa | 天天综合色天天综合 | 欧美另类变态 | 天堂a免费视频在线观看 | 女教师三级做受 | 女色在线观看免费视频 | 男男18视频免费网站 | 99精品影院| 国产精品亚洲va在线观看 | 美国xaxwaswaskino| 污黄在线观看 | 射逼网| 俄罗斯妈妈235| 国产精品怡红院在线观看 | 亚洲天堂男人的天堂 | 欧美性理论片在线观看片免费 | 动漫美女被羞羞产奶 | se01在线看片 | 7mav视频| 国产suv精品一区二区四区三区 | 国产极品麻豆91在线 | 午夜国产福利视频一区 | 日韩在线观看一区二区不卡视频 | 日本视频在线播放 |