第七十三篇 Django rest-framework 认证、权限、分页、频率

一、rest-framework 认证

1 介绍
由于我们每次给服务器发请求,由于Http的无状态,导致我们每次都是新的请求,
那么服务端需要对每次来的请求进行认证,看用户是否登录,以及登录用户是谁~~
那么我们服务器对每个请求进行认证的时候,不可能在每个视图函数中都写认证,rest-framwork中用户登录成功后给用户发送token,用下次请求携带token就可以认证。

2 用法

models.py

class User(models.Model):
    name = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)
    token = models.UUIDField(null=True, blank=True)

auth.py
定义认证类

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=2c14fc0a-f2da-45b0-aa9b-5a406dfff462
        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不合法")
        # request.user  request.auth
        return (user_obj, token)

views.py
测试认证

from rest_framework.views import APIView
from rest_framework.response import Response
from .models import User
from .auth import MyAuth
import uuid  #随机生成uuid码

class AuthTest(APIView):
    """登录认证后发送给前端token串"""
    def post(self, request):
        name = request.data.get("name", "")
        pwd = request.data.get("pwd", "")
        # 校验用户名和密码是否正确
        user_obj = User.objects.filter(name=name, pwd=pwd).first()
        if user_obj:
            user_obj.token = uuid.uuid4()
            user_obj.save()
            return Response(user_obj.token)
        else:
            return Response("用户名或密码错误")


class TestView(APIView):
    #认证token合法性
    authentication_classes = [MyAuth, ]

    def get(self, request):
        return Response("测试认证组件")
  1. 提交post登录请求后返回token码
    在这里插入图片描述
  2. 发送get请求并携带token进行验证
    在这里插入图片描述

二、rest-framework 权限

用户登录认证后判断type字段,来判断用户的权限是否合格

class MyPermission(object):
    message = "权限不足"
    def has_permission(self, request, view):
        # 权限逻辑
        # 认证已经执行完了
        user_obj = request.user  #认证对obj对象
        if user_obj.type == 1:
            return False
        else:
            return True

引用
views.py

from .serializers import BookSerializer
from rest_framework import viewsets
from utils.pagination import MyPaginator, LimitOffsetPaginator, CursorPaginator
from .permission import MyPermission
from .auth import MyAuth

class BookModelView(viewsets.ModelViewSet):
    queryset = models.Book.objects.all()
    serializer_class = BookSerializer
    authentication_classes = [MyAuth, ]
    permission_classes = [MyPermission, ]

使用token进行校验
在这里插入图片描述

三、rest-framework 分页

分页功能分为三种类型

1. 普通分页
http://127.0.0.1:8000/book/?page=1&size=2 可以指定页码和页码数据数量

from rest_framework import pagination

class MyPaginator(pagination.PageNumberPagination):
    page_size = 2
    page_query_param = 'page'  #手动配置路径上查询页的key的名称
    page_size_query_param = 'size' #手动配饰路径上显示最多信息条数的key
    max_page_size = 3 #最大不超过3

引用

class BookModelView(viewsets.ModelViewSet):
    queryset = models.Book.objects.all()
    serializer_class = BookSerializer
    pagination_class = MyPaginator #使用分页器

2. 偏移分页

http://127.0.0.1:8000/book/?limit=1&offset=1 页面数据数量和偏移量,offset=1&limit=1表示从第2条数据开始,往后1条

from rest_framework import pagination

class LimitOffsetPaginator(pagination.LimitOffsetPagination):
    default_limit = 1
    limit_query_param = 'limit'
    offset_query_param = 'offset'

引用

class BookModelView(viewsets.ModelViewSet):
    queryset = models.Book.objects.all()
    serializer_class = BookSerializer
    pagination_class = LimitOffsetPaginator #使用分页器

3. 游标加密分页

http://127.0.0.1:8000/book/?cursor=cj0xJnA9Mw%3D%3D 可以进行排序,游标后为加密内容,只有上一页和下一页

from rest_framework import pagination

class CursorPaginator(pagination.CursorPagination):
    cursor_query_param = 'cursor'
    ordering = 'id'  #按id进行排序
    page_size = 1

引用

class BookModelView(viewsets.ModelViewSet):
    queryset = models.Book.objects.all()
    serializer_class = BookSerializer
    pagination_class = CursorPaginator #使用分页器

四、rest-framework 频率

为了控制用户对某个url请求的频率,比如,一分钟以内,只能访问三次

1. 原理

  1. 拿到用户的IP地址
  2. 访问记录: {IP: [最近访问时间,…第一次的访问时间]}
  3. 确保这个列表最近的访问时间以及最远的访问时间差 《= 规定时间
  4. 判断列表的长度 《= 设置的访问频率

2.自定义频率

class MyThrottle(object):
    """
    一分钟允许访问5次
    """
    def __init__(self):
        self.history = []

    def allow_request(self, request, view):
        # 获取用户的IP地址
        ip = request.META.get("REMOTE_ADDR", "")
        # self.key = self.get_cache_key()
        # self.cache.get(self.key, [])
        if ip not in VISIT_RECORD:
            VISIT_RECORD[ip] = [time.time(),]
        else:
            history = VISIT_RECORD[ip]
            self.history = history
            history.insert(0, time.time())
            # 确保列表时间是允许范围之内
            while self.history[0] - self.history[-1] > 60:
                self.history.pop()
            # 判断列表长度
            if not len(self.history) <= 5:
                return False
        return True

    # 等待时间
    # [最近时间,      最老时间]
    def wait(self):
        return 60-(self.history[0] - self.history[-1])

引用

from .serializers import BookSerializer
from rest_framework import viewsets
from utils.pagination import MyPaginator, LimitOffsetPaginator, CursorPaginator
from .throttle import MyThrottle

class BookModelView(viewsets.ModelViewSet):
    queryset = models.Book.objects.all()
    serializer_class = BookSerializer
    pagination_class = CursorPaginator
    throttle_classes = [MyThrottle, ]

3. 内置频率类使用

class DRFThrottle(SimpleRateThrottle):
    scope = "WD"  #定义的名字key,方便setting中去取
    def get_cache_key(self, request, view):
        # 拿IP地址
        return self.get_ident(request)

settings.py

REST_FRAMEWORK = {
    "DEFAULT_THROTTLE_RATES": {
        "WD": "3/m"  #一分钟三次
    }
}

引用
views.py

from .serializers import BookSerializer
from rest_framework import viewsets
from utils.pagination import MyPaginator, LimitOffsetPaginator, CursorPaginator
from .throttle import MyThrottle

class BookModelView(viewsets.ModelViewSet):
    queryset = models.Book.objects.all()
    serializer_class = BookSerializer
    pagination_class = CursorPaginator
    throttle_classes = [DRFThrottle, ]

五、常见错误

“CSRF check no attribute ‘process_request’”

一定要添加在settings中的底部,底部生效,setting中的配置也需要用大写去配置。

REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": []
}

注意点:
url: {“get”:“list”}
继承 : viewsets.ModelviewSet
配置:序列化,分页,认证:token,频率

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值