qhfl-4 註冊-登陸-認證

 

認證

任何的項目都須要認證,當用戶輸入了用戶名和密碼,驗證經過,表明用戶登陸成功前端

那HTTP請求是無狀態的,下次這個用戶再請求,是不可能識別這個用戶是否登陸的redis

就要有本身的方式來實現這個認證,用戶登陸成功之後,生成一個隨機字符串,之後這個用戶再請求,都要攜帶這個隨機字符串。數據庫

就能夠根據這個字符串進行判斷這個用戶是否登陸,目的是前端發送請求的時候帶過來就能夠,之前的cookie,session是的一種解決方案,認證的時候也用過token的這種解決方案。django

token

用戶登陸成功後,生成一個隨機字符串token給前端返回json

那麼前端之後都攜帶這個token來訪問這樣只須要鑑別這個token來作認證後端

前端若是發送請求把token放在請求頭中看下的認證要怎麼寫服務器

序列化註冊數據cookie

測試的時候用的重寫create方法,真正開發前端傳過來的就是加密後的密文密碼
from rest_framework import serializers
from Course.models import Account
import hashlib


class RegisterSerializer(serializers.ModelSerializer):

    class Meta:
        model = Account
        fields = "__all__"

    def create(self, validated_data):
        pwd = validated_data["pwd"]
        pwd_salt = "luffy_password" + pwd   # 加鹽處理
        md5_str = hashlib.md5(pwd_salt.encode()).hexdigest()
        user_obj = Account.objects.create(username=validated_data["username"], pwd=md5_str)
        return user_obj

Login/serializers.py

 

註冊,登陸的視圖session

from rest_framework.views import APIView
from rest_framework.response import Response
from .serializers import RegisterSerializer
from utils.base_response import BaseResponse
from Course.models import Account
from utils.redis_pool import POOL
import redis
import uuid
from utils.my_auth import LoginAuth
from utils.geetest import GeetestLib
from django.http import HttpResponse
import json

# Create your views here.


class RegisterView(APIView):

    def post(self, request):
        res = BaseResponse()   # 實例化響應類
        # 用序列化器作校驗
        ser_obj = RegisterSerializer(data=request.data)
        if ser_obj.is_valid():
            ser_obj.save()
            res.data = ser_obj.data
        else:
            res.code = 1020
            res.error = ser_obj.errors
        return Response(res.dict)


class LoginView(APIView):

    def post(self, request):
        res = BaseResponse()
        username = request.data.get("username", "")
        pwd = request.data.get("pwd", "")
        user_obj = Account.objects.filter(username=username, pwd=pwd).first()
        if not user_obj:
            res.code = 1030
            res.error = "用戶名或密碼錯誤"
            return Response(res.dict)
        # 用戶登陸成功生成一個token寫入redis
        # 寫入redis  token : user_id
        conn = redis.Redis(connection_pool=POOL) # 從鏈接池獲取一個鏈接
        try:
            token = uuid.uuid4()
            conn.set(str(token), user_obj.id, ex=10000)
            # conn.set(str(token), user_obj.id)          # str(token) 用做key
            res.data = token
        except Exception as e:
            print(e)
            res.code = 1031
            res.error = "建立令牌失敗"
        return Response(res.dict)
Login/views.py

 

class BaseResponse(object):
    """
    封裝響應的類
    """
    def __init__(self):
        self.code = 1000
        self.data = None
        self.error = None


    @property
    def dict(self):
        return self.__dict__        # 返回字典
utils/base_response.py

認證器

http頭部發送的字段信息 key:valueide

在服務器接受時,須要加上前綴(而且大寫)例如 HTTP_KEY ,經過 request.META.get(HTTP_KEY) 獲取值

import redis

from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed

from .redis_pool import POOL
from Course.models import Account

CONN = redis.Redis(connection_pool=POOL)


class LoginAuth(BaseAuthentication):
    def authenticate(self, request):
        # 從請求頭中獲取前端帶過來的token。或者跟前端商量好
        token = request.META.get("HTTP_AUTHENTICATION", "")
        # print(request.META)
        # print(token)
        if not token:
            raise AuthenticationFailed("沒有攜帶token")
        # 去redis比對
        user_id = CONN.get(str(token))  # get沒有的值返回 None
        if user_id == None:
            raise AuthenticationFailed("token過時")  # 從新登陸設置token
        user_obj = Account.objects.filter(id=user_id).first()
        return user_obj, token
utils/my_auth.py

用到的redis鏈接池

import redis


POOL = redis.ConnectionPool(host="127.0.0.1", port=6379, decode_responses=True, max_connections=10)
utils/redis_pool.py

 

註冊用戶測試

測試發送密碼時爲密文。前端傳過來,後端加密後再與數據庫中的比對

以token爲key存放在redis中,登陸成功後返回生成的token數據(有有效期的),下次登陸時攜帶上。後端以傳過來的token 去reids中找,能找到就拿到用戶信息,不能就說明過時須要從新登陸,或者token不存在.

相關文章
相關標籤/搜索