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時,返回之前的錯誤返回資訊