【python之DRF學習】三大方法之認證

Unfool發表於2024-04-17
title:  【python之DRF學習】三大方法之認證
date:  2024-04-17 21:00:56 星期三
updated: 2024-04-17 21:01:00 星期三
description: 
cover: 

內建三大方法:

drf之APIView內部的必須會經過的三大認證/方法:
認證、許可權、頻率

一、認證元件

1、簡介

登入認證的限制

​ 認證元件是drf框架給我們提供的認證介面,它能夠在請求進入檢視函式/類前進驗證(例如:認證使用者是否登入),對不符合認證的請求進行攔截並返回校驗失敗的資訊

2、擴充套件

1、uuid模組:

介紹:用於生成一個隨機的字串
匯入模組:import uuid
生成隨機字串:token = str(uuid.uuid4())

3、基於認證類實現使用者訪問

3.1 使用步驟解析

訪問介面,必須登入後才能訪問,且保持使用者登陸狀態

# 有的介面需要登入後才能訪問;有的介面,不登入就能訪問,這是登入認證的限制   
# 寫一個登入介面,返回token。以後只要帶著token過來,就是登入了。不帶,就沒登入。
# 查詢所有不需要登入就能訪問
# 查詢單個,需要登入才能訪問

1. 透過認證類完成,使用步驟:
(1)寫一個認證類,繼承BaseAuthentication;
(2)重寫authenicate方法,在內部做認證;
(3)如果認證透過,返回2個值情況;[返回None或兩個值]----成功的情況下:(兩個值指的是返回使用者和token),失敗則返回None
(4)認證不透過拋AuthenticationFailed異常;
(5)只要返回了兩個值,在後續的request.user就是當前登入使用者;
(6)如果想讓某個檢視類登入後才能訪問    ---區域性使用和全域性使用

3.2 建立認證檔案Authenticate.py

from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from app01.models import UserToken

class LoginAuth(BaseAuthentication):
    def authenticate(self,request):
      #  在這裡做認證,校驗使用者是否登入(帶了token,並且能查到,就是登入,返回兩個值,否則就是沒登入,拋異常)
       # 使用者帶的token從哪取?後端人員定的:放在請求地址中
        token = request.META.get('HTTP_TOKEN')
       # 透過token表查詢該token是否是在表中有記錄
        user_token = UserToken.objects.filter(token=token).first()
        if user_token:
            user = user_token.user
            return user,token  # 返回兩個值,一個是當前登入使用者,一個是token
        else:
            raise AuthenticationFailed('未登陸,無法操作')
            
如果前端帶著cookie過來,經過session的中介軟體,如果登入了,在request.user中就有當前登入使用者;
drf沒有限制是否登入;
加了這個認證,如果沒有登入,就不允許往後訪問了.



# 另一種方式:
class LoginAuth(BaseAuthentication):
    def authenticate(self, request):
        # 在這裡實現認證,如果是登入的,繼續往後走返回兩個值,如果不是拋異常
        # 請求中是否攜帶token,判斷是否登入,放在位址列中
        token = request.query_params.get('token', None)
        if token:  # 前端傳入token了,去表中查。如果能查到,登入了,返回兩個值[固定的:當前登入使用者,token]
            user_token = UserToken.objects.filter(token=token).first()
            if user_token:
                return user_token.user, token
            else:
                # 沒有登入拋異常
                raise AuthenticationFailed('token認證失敗')
        else:
            raise AuthenticationFailed('token沒傳')

3.3 檢視層的使用方式

# 區域性
class BookView(ModelViewSet):
		authentication_classes = [LoginAuth,]

# 方式二:全域性配置(settings.py中配置)
	REST_FRAMEWORK={
		'DEFAULT_AUTHENTICATION_CLASSES':['app01.auth.LoginAuth',]}
  
# 區域性禁用---》登入介面   (使用全域性配置的前提下,當前禁用)
class PublishView(GenericViewSet):
    authentication_classes = []

    
#  登陸成功後如何攜帶token及返回
@action(methods=['post'], detail=False)
    def login(self, request):
        username = request.data.get('username')
        phone = request.data.get('phone')
        password = request.data.get('password')
        print(username, phone, password)
        user_obj = auth.authenticate(request,username=phone, password=password)
        print(user_obj)
        if user_obj:
       ###### 生成繫結token值並返回到前端####
            # 在userToken表中儲存一下:1 從來沒有登入過,插入一條,     2 登入過,修改記錄
            # 如果有就修改,如果沒有就新增  (if 自己寫)
            # kwargs 傳入的東西查詢,能找到,使用defaults的更新,否則新增一條
            token = str(uuid.uuid4())
            UserToken.objects.update_or_create(defaults={'token': token}, user=user_obj)
            return Response({'code': 102, 'msg': '登陸成功', 'token': token})
        else:
            return Response({'code': 103, 'msg': '使用者名稱或者密碼錯誤'})
			#####################################
 

3.4 models

新建userToken表用於反饋使用者是否攜帶token登陸
class UserToken(models.Model):
    token = models.TextField()
    user = models.OneToOneField(to='User', on_delete=models.CASCADE)  # 與前面建立的user表做一對一

當傳入錯誤的token時,返回之前的錯誤返回資訊
image

相關文章