DRF之三大认证
一、认证Authentication
认证主要用于登录认证,判断用户是否登录。在用户登录时返回一个随机的字符串,之后再访问时通过字符串判断用户是否登录。
登录接口举例:
编写步骤:
创建user表和一对一userToken表,在前端传入用户名密码,在后端接收去user表中对比,对比成功就让他登录。
登录成功后在userToken表中记录,并返回随机字符串,下次通过比对字符串判断是否登录。
models:
class User(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=32) user_type = models.IntegerField(choices=((1, '超级管理员'), (2, '普通管理员'), (3, '普通用户'))) # gender=models.IntegerField(choices=((1,"男"),(2,"女"),(0,"未知"))) # 1:男 2:女 0:未知 # user对象.get_字段名_display() 快速取出gender数字对应的中文 class UserToken(models.Model): user = models.OneToOneField(to=User,on_delete=models.CASCADE) token = models.CharField(max_length=32)
views:
from rest_framework.viewsets import ViewSet from rest_framework.decorators import action from .models import User, UserToken import uuid from rest_framework.response import Response # class UserView(ViewSetMixin,APIView): 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生成不重复的串---》理论上不重复 token = str(uuid.uuid4()) # 伪随机数生成,没有参数,重复概率,比其他的高一些 UserToken.objects.update_or_create(user=user, defaults={'token': token}) # 判断user是否存在,如果存在就更新,如果不存在就新增 return Response({'code': 100, 'msg': '登陆成功', 'token': token}) else: return Response({'code': 101, 'msg': '用户名或密码错误'})
urls:
from django.contrib import admin from django.urls import path, include from app01 import views from rest_framework.routers import SimpleRouter router = SimpleRouter() router.register('user', views.UserView, 'user') urlpatterns = [ path('admin/', admin.site.urls), path('', include(router.urls)), ]
认证类:
完成登录接口之后就可编写登录认证了:
编写步骤:
写一个类,继承BaseAuthentication,重写authenticate,在方法中做校验,校验是否登录,返回两个值,没有登录抛异常
新建一个auth.py:
from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed from .models import UserToken # 编写认证类 # 全局使用,局部使用 # 步骤:写一个类,继承BaseAuthentication,重写authenticate,在方法中做校验,校验是否登录,返回两个值,没有登录抛异常 class LoginAuth(BaseAuthentication): def authenticate(self, request): # 前端带过来的token,放在哪,是接口(我们)固定的 token = request.query_params.get('token') user_token = UserToken.objects.filter(token=token).first() if user_token: # 登录了 # 第一个:当前登录用户,第二个:token返回 return user_token.user, token else: # 抛出认证失败的异常 raise AuthenticationFailed('您没有登录')
配置认证:
全局配置方式:
可以在配置文件中配置全局默认的认证方案
REST_FRAMEWORK={ "DEFAULT_AUTHENTICATION_CLASSES":["app01.auth.LoginAuth",] }
局部配置方式:
在视图类中配置:
class UserView(ViewSet): authentication_classes = [LoginAuth]
局部禁用:
在全局配置后在指定的视图类中配置:
class UserView(ViewSet): authentication_classes = []
二 权限Permissions
权限控制可以限制用户对于视图的访问和对于具体数据对象的访问。
-
- 在执行视图的dispatch()方法前,会先进行视图访问权限的判断
- 在通过get_object()获取具体对象时,会进行模型对象访问权限的判断
权限举例:超级用户才能增删改,普通用户只有查单条和多条的权限。
编写步骤:写一个类,继承BasePermission,重写has_permission,判断如果有权限,返回True,如果没有权限,返回False
auth:
from rest_framework.permissions import BasePermission class UserPermission(BasePermission): def has_permission(self, request, view): self.message='您是:%s,没有权限'%request.user.get_user_type_display() # 没有权限的提示信息 # 如果有权限,返回True,没有权限返回False # 权限类,在认证类之后,request.user有了当前登录用户 user_type = request.user.user_type if user_type < 2: # 只要不是超级用户,就没有权限 return True else: return False
将5个接口分在两个视图写:
views:
# 普通用户,只能查看 from .auth import IPThrottle class BookView(GenericViewSet, ListModelMixin, RetrieveModelMixin): authentication_classes = [LoginAuth,] queryset = Book.objects.all() serializer_class = BookSerializer # 普通用户以上,才能修改。。。 from .auth import UserPermission class BookDetailView(GenericViewSet, CreateModelMixin, DestroyModelMixin, UpdateModelMixin): authentication_classes = [LoginAuth, ] permission_classes = [UserPermission, ] queryset = Book.objects.all() serializer_class = BookSerializer
使用方式:
全局使用:
可以在配置文件中配置全局默认的认证方案
REST_FRAMEWORK={ "DEFAULT_PERMISSION_CLASSES":["app01.auth.UserPermission",] }
局部使用:
在视图函数中配置:
class BookDetailView(GenericViewSet, CreateModelMixin, DestroyModelMixin, UpdateModelMixin): permission_classes = [UserPermission, ]
三、频率
可以对接口访问的频次进行限制,以减轻服务器压力。
使用方式:写一个类,继承SimpleRateThrottle,重写类属性:scope,和get_cache_key方法
get_cache_key返回什么,就以什么做限制,scope配置文件中要用
auth:
# 频率限制类 from rest_framework.throttling import BaseThrottle,SimpleRateThrottle class IPThrottle(SimpleRateThrottle): scope = 'minute_3' # 随便写 # 返回什么,就以什么做现在 def get_cache_key(self, request, view): # 限制ip地址---》request.META字典---》请求头中数据 return request.META.get('REMOTE_ADDR') # 客户端ip # return request.user.id # 用户id限制 class UserThrottle(SimpleRateThrottle): scope = 'minute_5' # 随便写 # 返回什么,就以什么做现在 def get_cache_key(self, request, view): return request.user.id
在配置文件中配置:
'DEFAULT_THROTTLE_RATES': { 'minute_3': '3/m' # minute_3是scope的字符串,一分钟访问3次 'minute_5':'5/m' }
局部使用:
在视图类中配置:
class BookView(GenericViewSet, ListModelMixin, RetrieveModelMixin): throttle_classes = [IPThrottle]
全局使用:
在配置文件中配置:
'DEFAULT_THROTTLE_CLASSES': ( # 全局配置频率类 'app01.auth.IPThrottle' ),
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通