前戏

大家都知道http协议是无状态的,每次发送请求他们怎么知道我们是不是登录过呢?我们可以在用户登录之后给用户一个“暗号”,下次请求的时候带着这个“暗号”来。我们拿自己存的和携带过来的进行对比,如果一样,就可以认为是登录过的。

认证

先来创建一张用户表

class User(models.Model):
    name = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)
    token = models.UUIDField(null=True, blank=True)  # 随机字符串

在进行数据库的迁移,在数据库里添加几条数据。

接下来就可以写我们的认证了,新建个py文件,写入如下内容,假设前端妹子给我们传来的token是在url里

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


class MyAuth(BaseAuthentication):
    def authenticate(self, request):  # 必须是这个函数名
        # 拿到前端传来的token,判断token是否存在
        token = request.query_params.get('token', '')
        if not token:
            raise AuthenticationFailed("缺少token")
        user_obj = User.objects.filter(token=token).first()
        if not user_obj:
            raise AuthenticationFailed("token不合法")
        return (user_obj, token)
DRF--认证和权限
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from course.models import Account
from django.utils.timezone import now  # 要用django提供的时间


class MyAuth(BaseAuthentication):
    def authenticate(self, request):
        if request.method == 'OPTIONS':  #过滤掉options请求
            return None
        # 拿到前端传来的token,请求头的数据都在request.META里
        # 比如前端把token放在请求头里:authenticate:85ada55664sfqq6
        # django会在前面加上 HTTP_ 并转为大写,也就是 HTTP_AUTHENTICATE
        # print(request.META)
        token = request.META.get('HTTP_AUTHENTICATE', '')

        # 判断是否有这个token
        if not token:
            raise AuthenticationFailed({"code": 1020, "error": "没有token"})
        user_obj = Account.objects.filter(token=token).first()
        if not user_obj:
            raise AuthenticationFailed({"code": 1021, "error": "token不合法"})

        # 判断token是否过期
        old_time = user_obj.create_token_time  # 数据库里存的token的时间
        now_time = now()  # 用django提供获取时间的方法
        if (now_time - old_time).days > 7:
            raise AuthenticationFailed({"code": 1022, "error": "token已过期,请重新登录"})
        return (user_obj, token)
token在请求头里

相关文章: