django-rest-framework中token认证的原理及如何自定义实现token认证

1. Token认证:

Token是一种用户身份的验证方式,通常叫做令牌验证。当用户第一次登录成功后,服务器会生成一个Token并将此Token返回给用户,以后用户只需要带上这个Token前来请求数据即可,无需再用用户名和密码。

2. Token验证过程

①首次登录时,客户端通过用户名与密码请求登录

②服务端收到请求并验证用户名与密码

③若验证通过,服务端会签发一个Token,该Token会保存在服务端的数据库中,并且也会返回给客户端

④客户端收到Token并存储起来,比如放在Cookie,SessionStorage,LocalStorage。

⑤客户端每次向服务端请求资源时都会带着Token

⑥服务端收到请求,然后验证客户端请求里面带着的Token,即将客户端的Token与本地数据库中的Token作对比,如果两个Token相同,说明用户曾登录成功过,则验证通过,服务端向客户端返回请求数据。

⑦若两个Token不同,则验证不通过,需要通过用户名和密码进行登录

3. 使用Token认证的原因:

当客户端多次向服务端请求数据时,服务端就需要多次从数据库中查询用户名和密码并进行比对,判断用户名和密码是否正确匹配,并作出相应提示。查询数据库是比较消耗资源的,这样无疑会增加服务器的运行压力。为了既能够验证用户登录情况又能够减轻服务器的压力,便引入了Token验证。Token一般是保存在内存中,这样的话就不用查询数据库,减少了频繁的查询数据库,使服务器更加健壮。


4. 自定义实现一个Token认证类

from django.http import JsonResponse

from rest_framework.views import APIView
from rest_framework import exceptions
from rest_framework.authentication import BaseAuthentication

from app01.models import UserInfo, UserToken


def md5(user):
    """对用户token进行加密"""
    import hashlib
    import time

    ctime = str(time.time())
    m = hashlib.md5(bytes(str(user), encoding="utf-8"))
    m.update(bytes(ctime, encoding="utf-8"))
    return m.hexdigest()


class AuthView(APIView):
    """用于用户登录认证,认证成功创建Token,如果token已经存在就更新token"""
    def post(self, request):
        username = request._request.POST.get("username", "")
        password = request._request.POST.get("password", "")
        try:
            user = UserInfo.objects.get(username=username, password=password)
        except UserInfo.DoesNotExist:
            res = {"status": 1000, "msg": "用户名或密码错误"}
        else:
            # 创建唯一的用户token
            token = md5(user)
            # 没有就创建,有了就更新
            UserToken.objects.update_or_create(user=user, defaults={"token": token})
            res = {"status": 1001, "msg": "认证成功", "token": token}
        return JsonResponse(res)


class Authtication(BaseAuthentication):
    """用户是否登录成功认证类, 如果有token代表登录成功,如果没token代表登录失败"""
    def authenticate(self, request):
        token = request._request.GET.get("token")
        user_token = UserToken.objects.filter(token=token).first()
        if not user_token:
            raise exceptions.AuthenticationFailed("用户认证失败")
        # 传递的这个元组就会赋值给request对象的两个属性:request.user, request.auth
        return (user_token.user, token)

    def authenticate_header(self, request):
        pass


class OrderViewAPIView(APIView):
    authentication_classes = [Authtication]

    def get(self, request):
        # 此处的两个变量就是认证类里面认证成功后传递过来的元组
        print(request.user, request.auth)
        return JsonResponse({"status": 200, "msg": "首页"})

猜你喜欢

转载自blog.csdn.net/weixin_42289273/article/details/115323907
今日推荐