drf組件之jwt認證模塊
一、認證規則
全稱:json web token
解釋:加密字符串的原始數據是json,后台產生,通過web傳輸給前台存儲
格式:三段式 - 頭.載荷.簽名 - 頭和載荷用的是base64可逆加密,簽名用md5不可逆加密
內容:
頭(基礎信息,也可以為空):加密方式、公司信息、項目組信息、...
載荷(核心信息):用戶信息、過期時間、...
簽名(安全保障):頭加密結果+載荷加密結果+服務器秘鑰 的md5加密結果
認證規則:
后台一定要保障 服務器秘鑰 的安全性(它是jwt的唯一安全保障)
后台簽發token(login接口 ) -> 前台存儲 -> 發送需要認證的請求帶着token -> 后台校驗得到合法的用戶 -> 權限管理
為什么要有jwt認證:
1)服務器壓力小, 后台不需要存儲token,只需要存儲簽發與校驗token的算法,效率遠遠大於后台存儲和取出token完成校驗
2) jwt算法認證,更適合服務器集群部署
二、認證模塊
安裝:pip install djangorestframework-jwt
模塊包:rest_framework_jwt
采用drf-jwt框架,后期任務只需要書寫登錄
為什么要重寫登錄:drf-jwt只完成了賬號密碼登錄,我們還需要手機登錄,郵箱登錄
為什么不需要重寫認證類:因為認證規則已經完成且固定不變,變得只有認證字符串的前綴,前綴可以在配置文件中配置
三、JWT使用
jwt配置;
在settings.py文件中配置,如果不配置,默認走jwt默認的
jwt插件的三個接口:
在urls.py中配置
在postman中測試一下簽發token
注意:上面三個接口都是發送POST請求
四、利用JWT實現多方式登錄
注:APIResponse 為自定義Response對象
# views.py
from rest_framework.views import APIView
from . import models,serializers
from utils.response import APIResponse
class LoginAPIView(APIView):
# 登錄接口應該禁用所有的認證和、權限,因為不管是誰都應該能進來
authentication_classes = []
permission_classes = []
def post(self, request, *args, **kwargs):
# 將數據傳到序列化組件進行校驗
user_ser = serializers.LoginSerializer(data=request.data)
user_ser.is_valid(raise_exception=True)
return APIResponse(msg='login success', data={
'username': user_ser.user.username,
'token': user_ser.token
})
注意:
通過user對象生成payload載荷
payload = jwt_payload_handler(user)
通過payload簽發token
token = jwt_encode_handler(payload)
# serializer.py
from rest_framework.serializers import ModelSerializer, CharField, ValidationError, SerializerMethodField
from . import models
from django.contrib.auth import authenticate
import re
from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler
class LoginSerializer(ModelSerializer):
username = CharField(write_only=True)
password = CharField(write_only=True)
class Meta:
model = models.User
fields = ('username', 'password')
def validate(self, attrs):
# user_obj = authenticate(**attrs)
# if not user_obj:
# raise ValidationError('用戶名或密碼錯誤')
# 賬號密碼登錄 ==》 多方式登錄
user = self._many_method_login(**attrs)
# 通過user對象生成payload載荷
payload = jwt_payload_handler(user)
# 通過payload簽發token
token = jwt_encode_handler(payload)
# 將user和token存放在序列化對象中,方便返回到前端去
self.user = user
self.token = token
return attrs
# 多方式登錄 (用戶名、郵箱、手機號三種方式登錄)
def _many_method_login(self, **attrs):
username = attrs.get('username')
password = attrs.get('password')
# 利用正則匹配判斷用戶輸入的信息
# 1.判斷郵箱登錄
if re.match(r'.*@.*', username):
user = models.User.objects.filter(email=username).first() # type: models.User
# 2.判斷手機號登錄
elif re.match(r'^1[3-9][0-9]{9}$',username):
user = models.User.objects.filter(mobile=username).first()
# 3.用戶名登錄
else:
user = models.User.objects.filter(username=username).first()
if not user:
raise ValidationError({'username': '賬號有誤'})
if not user.check_password(password):
raise ValidationError({'password': '密碼錯誤'})
return user
使用postman測試代碼:
五、前后台分離模式下信息交互規則
"""
1)任何人都能直接訪問的接口
請求不是是get、還是post等,不需要做任何校驗
2)必須登錄后才能訪問的接口
任何請求方式都可能做該方式的限制,請求必須在請求頭中攜帶認證信息 - authorization
3)前台的認證信息獲取只能通過登錄接口
前台提供賬號密碼等信息,去后台換認證信息token
4)前台如何完成登錄注銷
前台登錄成功一般在cookie中保存認證信息token,分離注銷就是前台主動清除保存的token信息
"""