今天來(lái)記錄一下涡匀,使用django開(kāi)發(fā)中盯腌,經(jīng)常用到的注冊(cè)、登陸陨瘩、認(rèn)證攜帶token這些基本的功能腕够,基本每一個(gè)網(wǎng)站開(kāi)發(fā)都離不開(kāi),好記性不如爛筆頭舌劳,開(kāi)始
注冊(cè)
1:先定義路由帚湘,
from django.urls import path
from .views import RegisterView,LoginView,TestAuthView
urlpatterns = [
path('register/', RegisterView.as_view()),
]
2:定義具體的視圖函數(shù)
import uuid
import redis
from django.shortcuts import render
from rest_framework.views import APIView
from .serializer import RegisterSerializer
from utils.base_response import BaseResponse
from rest_framework.response import Response
from Course.models import Account
from utils.redis_pool import POOL
from utils.test_auth import LoginAuth
#注冊(cè)
class RegisterView(APIView):
def post(self, request):
result = BaseResponse()
# 用序列化器做校驗(yàn)
ser_obj = RegisterSerializer(data=request.data)
# 驗(yàn)證通過(guò)
if ser_obj.is_valid():
ser_obj.save()
result.data = ser_obj.data
else:
result.code = 500
result.error = ser_obj.errors
return Response(result.dict)
ps:這里注意的是,注冊(cè)必須post方法哦蒿囤,為了安全客们,提交之前會(huì)調(diào)用RegisterSerializer這個(gè)序列化器,進(jìn)行參數(shù)的校驗(yàn)材诽,驗(yàn)證通過(guò)則調(diào)用save方法底挫,進(jìn)行數(shù)據(jù)庫(kù)保存,認(rèn)證失敗脸侥,返回錯(cuò)誤字典給前端建邓,上代碼
3:定義序列化器
from rest_framework import serializers
from Course.models import Account
import hashlib
class RegisterSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = '__all__'
# 重寫(xiě)報(bào)錯(cuò)新增的方法
def create(self, validated_data):
pwd = validated_data['pwd']
# 進(jìn)行加密
pwd_sawt = "dong" + pwd
md5_str = hashlib.md5(pwd_sawt.encode()).hexdigest()
# save
user_obj = Account.objects.create(username=validated_data['username'], pwd=md5_str)
return user_obj
ps:這里使用了md5加密密碼,防止密碼明文提交睁枕,保證安全
好了官边,準(zhǔn)備測(cè)試看效果
使用post軟件進(jìn)行測(cè)試沸手,
可以看到用戶創(chuàng)建成功了,數(shù)據(jù)庫(kù)中也生成了對(duì)應(yīng)的記錄
登陸
接下來(lái)就是登陸功能了注簿,使用我們剛剛創(chuàng)建好的用戶契吉,來(lái)登陸看看是否可以登陸成功了
1:定義路由
from django.urls import path
from .views import RegisterView,LoginView,TestAuthView
urlpatterns = [
path('register/', RegisterView.as_view()),
path('login/', LoginView.as_view()),
]
2:定義視圖函數(shù)
import uuid
import redis
from django.shortcuts import render
from rest_framework.views import APIView
from .serializer import RegisterSerializer
from utils.base_response import BaseResponse
from rest_framework.response import Response
from Course.models import Account
from utils.redis_pool import POOL
class LoginView(APIView):
def post(self, request):
result = BaseResponse()
username = request.data.get('username', '')
pwd = request.data.get('pwd', '')
user_obj = Account.objects.filter(username=username, pwd=pwd).first()
# 用戶驗(yàn)證失敗
if not user_obj:
result.code = 500
result.error = "用戶么或者密碼錯(cuò)誤"
return Response(result.dict)
# 用戶驗(yàn)證成功,存入redis
# 寫(xiě)入redis token : user_id
conn = redis.Redis(connection_pool=POOL)
try:
token = uuid.uuid4()
# conn.set(str(token), user_obj.id, ex=10)
conn.set(str(token), user_obj.id,ex=10)
result.data = token
except Exception as e:
print(e)
result.code = 501
result.error = "創(chuàng)建令牌失敗啦"
return Response(result.dict)
ps:這里使用redis進(jìn)行輔助诡渴,將驗(yàn)證成功的用戶放入redis數(shù)據(jù)庫(kù)捐晶,然后方便后續(xù)直接可以通過(guò)token,獲取用戶ID妄辩,{token : user_id}惑灵,這樣就可以快速獲取用戶ID,查詢用戶眼耀,方便其他接口的調(diào)用英支,或者傳參使用,
ex=10,代表在redis中的過(guò)期時(shí)間哮伟,單位是秒(seconds)
獻(xiàn)上工具類(lèi)代碼
class BaseResponse(object):
def __init__(self):
self.code = 200
self.data = None
self.error = None
@property
def dict(self):
return self.__dict__
import redis
POOL = redis.ConnectionPool(host="127.0.0.1", port=6379, decode_responses=True, max_connections=10)
3:登陸測(cè)試干花,看效果
必須使用加密后的密碼登陸,因?yàn)槲覀冏隽思用苊魑奶幚?/p>
認(rèn)證
當(dāng)我們?cè)谡{(diào)用其他的接口的時(shí)候澈吨,必須在header中攜帶一個(gè)請(qǐng)求頭把敢,這個(gè)請(qǐng)求頭攜帶者token,從而告訴服務(wù)器谅辣,我們已經(jīng)登陸過(guò)了,或者沒(méi)有登陸婶恼,因?yàn)閔ttp是一個(gè)無(wú)狀態(tài)協(xié)議桑阶,無(wú)法判斷這次請(qǐng)求的用戶到底是誰(shuí),那么接下來(lái)我們就看下具體怎實(shí)現(xiàn)的吧勾邦?
1:先定義一個(gè)路由蚣录,就用TestAuthView來(lái)實(shí)現(xiàn)具體的視圖吧
from django.urls import path
from .views import RegisterView,LoginView,TestAuthView
urlpatterns = [
path('register/', RegisterView.as_view()),
path('login/', LoginView.as_view()),
path('test_auth/', TestAuthView.as_view()),
]
2:調(diào)用LoginAuth進(jìn)行驗(yàn)證
import uuid
import redis
from django.shortcuts import render
from rest_framework.views import APIView
from .serializer import RegisterSerializer
from utils.base_response import BaseResponse
from rest_framework.response import Response
from Course.models import Account
from utils.redis_pool import POOL
from utils.test_auth import LoginAuth
class TestAuthView(APIView):
authentication_classes = [LoginAuth]
def get(self, request):
return Response('我在進(jìn)行認(rèn)證登陸測(cè)試哦')
3:登陸認(rèn)證
import redis
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from .redis_pool import POOL
import redis
from Course.models import Account
CONN = redis.Redis(connection_pool=POOL)
class LoginAuth(BaseAuthentication):
def authenticate(self, request):
# 從請(qǐng)求頭中獲取前端帶過(guò)來(lái)的token
token = request.META.get('HTTP_AUTHENTICATION', '')
if not token:
raise AuthenticationFailed('沒(méi)有攜帶token..')
# 去redis進(jìn)行比較
user_id = CONN.get(str(token))
if not user_id:
raise AuthenticationFailed('token過(guò)期啦..')
else:
user_obj = Account.objects.filter(pk=user_id).first()
return user_obj, token
ps:所有驗(yàn)證類(lèi)都必須繼承BaseAuthentication基類(lèi),重寫(xiě)authenticate方法
***從請(qǐng)求頭中獲取前端帶過(guò)來(lái)的token
4.從請(qǐng)求頭中獲取前端帶過(guò)來(lái)的token
5.驗(yàn)證token是否存在
6.驗(yàn)證token和reidis中的user_id比較
7.將次user_id在數(shù)據(jù)中查詢眷篇,返回用戶對(duì)象和token
8:測(cè)試看效果
這里我們?cè)趐ost發(fā)起請(qǐng)求萎河,不加AUTHENTICATION
這里我們?cè)趐ost發(fā)起請(qǐng)求,加HTTP_AUTHENTICATION
這里我們?cè)趐ost發(fā)起請(qǐng)求蕉饼,加AUTHENTICATION虐杯,但是我們隨便寫(xiě)個(gè)
這里我們?cè)趐ost發(fā)起請(qǐng)求,加AUTHENTICATION,用正確的上一步登陸返回的token作為值來(lái)測(cè)試昧港,
認(rèn)證成功擎椰!
每天進(jìn)步一點(diǎn)點(diǎn),千里之行始于足下创肥!