认证

认证的作用是告知api是那个用户在请求。

需要新建一个UserInfo的Model。

前后端不分离项目可以用Form与ModelForm代替。

认证类的简单写法

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


class MyAuth(BaseAuthentication):

    def authenticate(self, request):
        # 通过唯一标识找到用户
        token = request.query_params.get('token')
        user_obj = models.User.objects.filter(token=token).first()

        if user_obj:
            # 返回:第一个是用户对象,第二个是token的值
            return user_obj, token
        raise AuthenticationFailed('认证失败')

全局默认配置:所有类都进行认证

REST_FRAMEWORK = {    
    # 后面是认证类在项目中的位置的路径
    "DEFAULT_AUTHENTICATION_CLASSES": ['user.auth.MyAuth']
}

视图中单独配置

注意:视图中的配置会“覆盖”全局默认配置,如果在视图中设置为空列表,那么这个类就不进行认证了!

from user.auth import MyAuth

class TestView(APIView):
    # 配置认证的类,注意放在列表中
    authentication_classes = [MyAuth]

    def get(self, request):
        return Response({'msg': ok'})

权限

权限组件的作用是:校验当前访问的用户能否获取到正确的结果。

特别注意:

  1. 权限组件的使用是建立在认证组件校验成功的前提下的!
  2. 如果用户没有登录,此时它是一个“匿名用户”,匿名用户只能访问不用登录的页面以及进行相关的操作。

权限类的简单写法

from rest_framework.permissions import BasePermission

class VipPermission(BasePermission):
    # 错误的提示
    message = '没有访问权限,请联系管理员'

    def has_permission(self, request, view):
        # 这里其实可以跟“权限组件”联系起来~通过用户对象连续跨表找到路由,进行权限的校验
        if not request.auth:
            # 没有认证就没有权限
            return False

        # 这里做了简单的校验,其实可以跟权限组件联系起来的
        if request.user.vip:
            return True
        else:
            return False

全局默认配置:所有类都进行权限校验

REST_FRAMEWORK = {
   # 校验 
    "DEFAULT_AUTHENTICATION_CLASSES": ['user.auth.MyAuth'],

   # 权限
    "DEFAULT_PERMISSION_CLASSES":['user.permission.VipPermission']
}

视图中单独配置

注意:视图中的配置会“覆盖”全局默认配置!如果在视图中设置为空列表,那么这个类就不进行权限校验了!

from user.permission import VipPermission

class TestView(APIView):
    # authentication_classes = []
    permission_classes = [VipPermission]

频率限制

顾名思义,这个组件是用来限制用户访问网站的频率的。

一、自定义访问频率限制的类:

from rest_framework.throttling import BaseThrottle,SimpleRateThrottle
import time
from rest_framework import exceptions
visit_record = {}
class VisitThrottle(BaseThrottle):
    # 限制访问时间
    VISIT_TIME = 10
    VISIT_COUNT = 3

    # 定义方法 方法名和参数不能变
    def allow_request(self, request, view):
        # 获取登录主机的id
        id = request.META.get('REMOTE_ADDR')
        self.now = time.time()

        if id not in visit_record:
            visit_record[id] = []

        self.history = visit_record[id]
        # 限制访问时间
        while self.history and self.now - self.history[-1] > self.VISIT_TIME:
            self.history.pop()
        # 此时 history中只保存了最近10秒钟的访问记录
        if len(self.history) >= self.VISIT_COUNT:
            return False
        else:
            self.history.insert(0, self.now)
            return True

    def wait(self):
        return self.history[-1] + self.VISIT_TIME - self.now

1.在全局中进行的全局配置

REST_FRAMEWORK = {
   # 校验 
    "DEFAULT_AUTHENTICATION_CLASSES": ['user.auth.MyAuth'],

   # 权限
    "DEFAULT_PERMISSION_CLASSES":['user.permission.VipPermission'],

  # 频率限制
  "DEFAULT_THROTTLE_CLASSES":["user.throttles.VisitThrottle",]
}

2.视图中进行的局部配置

from user.throttles import *

class BookViewSet(generics.ListCreateAPIView):
    throttle_classes = [VisitThrottle,]


    queryset = Book.objects.all()
    serializer_class = BookSerializers

二、Django中自带的访问频率限制的类

1.配置

REST_FRAMEWORK = {

    # 认证
    "DEFAULT_AUTHENTICATION_CLASSES": ['user.auth.MyAuth'],
    # 权限
    "DEFAULT_PERMISSION_CLASSES":['user.permission.VipPermission']
    # 频率
    "DEFAULT_THROTTLE_CLASSES": [
        # 处理的类
        'user.throttle.MyThrottle',
    ],
    'DEFAULT_THROTTLE_RATES': {
        # 视图
        "xxxxx": '5/m',
        "x1": '1/s',
    }

}

REST_FRAMEWORK = {

    "DEFAULT_AUTHENTICATION_CLASSES": ['user.auth.MyAuth'],
    "DEFAULT_PERMISSION_CLASSES":['user.permission.VipPermission']

    "DEFAULT_THROTTLE_CLASSES": [
        'user.throttle.MyThrottle2',
    ],
    'DEFAULT_THROTTLE_RATES': {
        "xxxxx": '5/m',
        "x1": '1/s',
    }

}

2.视图中调用

class TestView(APIView):

    throttle_scope = 'x1'

    def get(self, request):
        return Response({'msg': 'ok'})


class Test2View(APIView):
    throttle_scope = 'xxxxx'

    def get(self, request):
        return Response({'msg': 'ok'})