drf-认证、权限、频率

【一】前言

# 三大认证依次执行
    -认证类
    -权限类
    -频率类
    
# APIView---->dispatch---》 self.initial(request, *args, **kwargs)--》
    self.perform_authentication(request)
    self.check_permissions(request)
    self.check_throttles(request)

【二】登录接口(添加认证)

  • 用户表 models.py

from django.db import models
​
​
# Create your models here.
​
class User(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)
    age = models.IntegerField()
​
​
class UserToken(models.Model):
    token = models.CharField(max_length=64)
    user = models.OneToOneField(to=User, on_delete=models.CASCADE)
  • 视图类 views.py

from rest_framework.viewsets import ViewSet, GenericViewSet
from rest_framework.decorators import action
from rest_framework.response import Response
from .models import User, UserToken
​
​
class UserView(ViewSet):
    @action(methods=['POST'], detail=False)
    def login(self, request):
        # 取出前端传入的用户和密码
        username = request.data.get("username")
        password = request.data.get("password")
        # 去数据库校验用户名和密码是否正确
        user = User.objects.filter(username=username, password=password).first()
        if user:
            # 用户名密码正确,签发token
            # 使用uuid生成一个随机字符串   uuid:可以生成不重复的字符串
            token = str(uuid.uuid4())
            # 保存到数据库,update_or_create有则修改,无则添加
            UserToken.objects.update_or_create(defaults={"token": token}, user=user)
            return Response({"code": 200, "msg": "登录成功", "token": token})
           
        else:
            return Response({"code": 403, "msg": "用户名或密码错误"})
​
  • 自动生成路由并添加 urls.py

from rest_framework.routers import SimpleRouter
from .views import UserView
​
# 实例化路由对象
router = SimpleRouter()
router.register("user", UserView, "user")
urlpatterns = [
]
urlpatterns += router.urls

【三】认证

  • 添加book模型表 models.py

class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.IntegerField()
  • 视图类 views.py

from rest_framework.mixins import ListModelMixin, RetrieveModelMixin, UpdateModelMixin
from .models import Book
from .serializer import BookSerializer
from .auth import LoginAuth
​
​
class BookView(GenericViewSet, ListModelMixin, RetrieveModelMixin, UpdateModelMixin):
    authentication_classes = [LoginAuth]
    queryset = Book.objects.all()
    serializer_class = BookSerializer
  • 序列化类serializer.py

from .models import Book
from rest_framework import serializers
​
​
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'
  • 添加路由 urls.py

from .views import UserView,BookView
​
router.register("books", BookView, "book")
  • 编写认证类

1 新创建一个py文件 auth ,写一个登录认证类LoginAuth,继承BaseAuthentication
2 在类中,重写authenticate
3 在方法中完成,登录信息的认证
	# 要求用户把 登录信息token 放在请求头中 
    # 取的方法:request.META.get("HTTP_TOKEN")
4 如果认证通过,返回两个值  后续在视图类views.py的方法中 request.user 拿到的就是 第一个参数返回的值
	return user_token.user, token
5 认证失败,抛出异常
6 把认证类配置在视图类上--》视图类就会受认证类的控制
	局部配置
7 全局配置:配置文件setting中
	authentication_classes = [LoginAuth]
8 局部禁用--》登录要局部禁用,空就相当于没有限制
	authentication_classes = []
  • auth.py

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


class LoginAuth(BaseAuthentication):
    def authenticate(self, request):
        # 要求用户把登录信息带着请求头中
        # 取出token
        token = request.META.get('HTTP_TOKEN')
        # 校验用户
        user_token = UserToken.objects.filter(token=token).first()
        if not user_token:
            # 只能抛出drf异常
            raise AuthenticationFailed("当前还未登录,请先前往登录!")
        else:
            # 校验通过返回的第一个参数,在views中给了request.user
            return user_token.user, token
【tips】
在settings中,导入一些不用的模块,可能会导致项目启动不了
例如:from app01.auth import LoginAuth

【四】权限

  • 编写权限类

1 新创建一个py文件 permission.py  写一个权限校验类CommonPermission  继承 BasePermission
2 在类中重写has_permission方法
3 在方法中完成,权限的校验
4 如果有权限,返回True
5 如果没有权限,返回False,通过  self.message  修改 错误提示
6 把权限类配置在视图类上--》视图类就会受权限类的控制
	-局部配置: permission_classes = [CommonPermission]
7 全局配置:配置文件
	'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.AllowAny',
    ],
8 局部禁用--》登录要局部禁用
	 permission_classes = []
  • permission.py

from rest_framework.permissions import BasePermission


class CommonPermission(BasePermission):
    def has_permission(self, request, view):
        # 判断用户是否有权限
        # 取出用户的类型
        user_type = request.user.user_type
        # 对类型进行判断
        # 判断是否为超级会员
        if user_type == 3:
            # 如果有权限,返回True
            return True
        # 判断是否为普通会员
        elif user_type == 2 and request.method in ["GET"]:
            return True
        else:
            self.message = f"你是{request.user.get_user_type_display()},不是会员用户,请升级会员!"
            return False

【五】频率

  • 编写频率类

限制用户的访问频次
	- 限制条件是唯一的:ip地址,用户id,设备id号
    
1 新创建一个py文件 throttles.py  写一个频率校验类CommetnThrottle  继承 SimpleRateThrottle
2 在类中重写get_cache_key方法
3 在方法中完成,频率的校验
4 rate = '3/m' 一分钟三次
5 把频率类配置在视图类上--》视图类就会受频率类的控制
   局部配置: throttle_classes = [CommontThrottle]
6 全局配置:配置文件
     DEFAULT_THROTTLE_CLASSES': ['自己写的类'],
7 局部禁用--》登录要局部禁用
     throttle_classes = []
  • throttles.py

from rest_framework.throttling import SimpleRateThrottle


# SimpleRateThrottle继承自 BaseThrottle 因为使用更方便所以导入它就可以了

class CommentThrottle(SimpleRateThrottle):
    # 一分钟三次
    rate = '3/m'

    def get_cache_key(self, request, view):
        # 返回什么,就以什么做限制
        # ip限制
        ip = request.META.get('REMOTE_ADDR')
        # id限制
        # user_id = request.user.id
        return ip
  • 23
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值