认证Authentication(5星)

认证逻辑及编写步骤

逻辑

认证类:用来校验用户是否登录,如果登录了,继续往下走,如果没有登录,直接返回

编写步骤

   -第一步:写一个类,继承BaseAuthentication,重写authenticate,在方法中做校验,校验是否登录,返回两个值,没有登录抛异常
-第二步:全局配置,局部配置
-全局配置:配置文件中
REST_FRAMEWORK={
"DEFAULT_AUTHENTICATION_CLASSES":["app01.auth.LoginAuth",]
}
-局部配置:在视图类中
class UserView(ViewSet):
authentication_classes = [LoginAuth] -局部禁用:
class UserView(ViewSet):
authentication_classes = [] # 认证类中返回的两个变量,干啥用了
-返回的第一个,给了request.user,就是当前登录用户
-返回的第二个,给了request.auth,就是token串

使用方法

新建一个功能为认证的py文件,然后在里面书写下面代码

from rest_framework.authentication import BaseAuthentication   # 类必须继承这个
from rest_framework.exceptions import AuthenticationFailed # 认证报错的异常 class xxx(BaseAuthentication):
def authenticate(self, request): # 必须重写这个方法,不然报错
逻辑逻辑逻辑...
if 验证通过:
return
else:
raise AuthenticationFailed('验证不通过')

在需要验证的视图类里

class BookAPIView(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookModelSerializer
# 只需要把下面这句话加上就行了 那么在执行该视图类前会判断该类是否通过验证
# 通过则正常执行,不通过则返回报错信息
authentication_classes = [xxx, ]

案例

登陆认证

在路由里:

from rest_framework.routers import SimpleRouter

router = SimpleRouter()
router.register('book', views.BookAPIView) urlpatterns = [
path('login/', views.UserView.as_view()),
path('', include(router.urls))
]

在models.py里:

class User(models.Model):
username = models.CharField(max_length=32)
password = models.CharField(max_length=32) class UserToken(models.Model):
user = models.OneToOneField(to='User', on_delete=models.CASCADE)
token = models.CharField(max_length=64)

在认证的py文件里:

# 新建一个py文件auth.py
from rest_framework.authentication import BaseAuthentication
from .models import UserToken
from rest_framework.exceptions import AuthenticationFailed class LoginAuth(BaseAuthentication):
def authenticate(self, request):
#### 写认证规则
# 取出用户携带的token
token = request.query_params.get('token')
# 去数据库查找
user_token = UserToken.objects.filter(token=token)
if user_token:
# 说明登陆过
'''
如果返回user,token,后面视图类中通过request对象,可以取到当前登录用户
'''
return
else:
# 没有登录,不能继续往后走,抛认证失败异常
raise AuthenticationFailed('您未登陆')

在视图函数里:

from app01.auth import LoginAuth

class BookAPIView(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookModelSerializer
authentication_classes = [LoginAuth, ] # 这里验证是否登陆

因为数据库内已经有一个token,所以拿这个token验证

全局使用

在django的settings.py中设置

这里不要手打,容易出错,用模块导入的形式来写

from app01.auth import LoginAuth

然后把import删除加个点

app01.auth.LoginAuth

REST_FRAMEWORK={
"DEFAULT_AUTHENTICATION_CLASSES":["app01.auth.LoginAuth",]
}

局部使用

# 局部使用,只需要在视图类里加入:
authentication_classes = [LoginAuth, ]
# 局部禁用 直接写个空列表就行了
authentication_classes = []

认证类的查找顺序

视图类自己中的authentication_classes > 项目的配置文件 > drf的配置文件

源码分析(2星)

# APIView--->dispathch方法的-----》self.initial(request, *args, **kwargs)(497行)---》APIView的initial方法----》有三句话
self.perform_authentication(request) # 认证
self.check_permissions(request) # 权限
self.check_throttles(request) # 频率

补充知识点:

权限Permissions(4星)

使用方法

在一个py文件内:

from rest_framework.permissions import BasePermission  # 继承这个类
class xxx(BasePermission):
def has_permission(self, request, view): # 重写此方法
# 写权限逻辑
if 符合权限:
return True # 有权限
else:
return False # 无权限

在需要验证的视图类里:

# 把权限的py文件导入
class BookAPIView(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookModelSerializer
# 只需要把下面这句话加上就行了 那么在执行该视图类前会判断该类是否有权限
# 没权限则不会执行该视图类
permission_classes = [xxx, ]

全局使用

REST_FRAMEWORK={
"DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",]
}

局部使用

# 局部使用只需要在视图类里加入:
permission_classes = [UserPermission,] # 局部禁用
permission_classes = [] # 什么都不写就是禁用

源码分析(2星)

和认证的源码差不多,只是没有和Request联系

APIView---》dispatch-self.initial---》self.check_permissions(request)
for permission in self.get_permissions():
if not permission.has_permission(request, self):
self.permission_denied(
request,
message=getattr(permission, 'message', None),
code=getattr(permission, 'code', None)
)

频率Throttling

可以对接口访问的频次进行限制,以减轻服务器压力。

一般用于付费购买次数,投票等场景使用.

继承SimpleRateThrottle使用方法

这里继承SimpleRateThrottle

在一个py文件内:

from rest_framework.throttling import SimpleRateThrottle  # 必须继承这个类

class xxx(SimpleRateThrottle):
scope = 'ip_throtle' # 这个参数必须配置,不然会报错,后面的字符串随便写
# 或者
rate = '3/m' # 这样写下面的配置文件里的'ip_throtle': '3/m'就可以不用写了
def get_cache_key(self, request, view):
# 返回客户端IP 返回谁,就以谁做限制 按ip限制
return request.META.get('REMOTE_ADDR')
# 或
return self.get_ident(request) # 如果有代理也会返回真实的客户端IP

在配置文件settings.py内:

REST_FRAMEWORK = {
'DEFAULT_THROTTLE_RATES': {
'ip_throtle': '3/m' # key要跟类中的scope对应 '3/m'意思是每分钟最多访问3次
}
} # 使用 `second`, `minute`, `hour` 或`day`来指明周期。

在需要验证限流的视图类里:

from app01.auth import xxx

class BookAPIView(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookModelSerializer
throttle_classes = [xxx, ] # 在这里添加验证限流

全局使用

REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': ['app01.auth.MyThrottle'], # 全局使用
'DEFAULT_THROTTLE_RATES': {
'ip_throtle': '3/m' # key要跟类中的scope对应 '3/m'意思是每分钟最多访问3次
}
}

局部使用

class BookView(ViewSetMixin,ListAPIView):
throttle_classes = [MyThrottle,]

源码分析SimpleRateThrottle(2星)

源码分析BaseThrottle(2星)

APIVIew的dispatch---》self.initial(request, *args, **kwargs)----》
def check_throttles(self, request): throttle_durations = []
for throttle in self.get_throttles():
if not throttle.allow_request(request, self):
throttle_durations.append(throttle.wait()) if throttle_durations:
durations = [
duration for duration in throttle_durations
if duration is not None
] duration = max(durations, default=None)
self.throttled(request, duration)

继承BaseThrottle使用方法

# 自定义的逻辑
#(1)取出访问者ip
#(2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问,在字典里,继续往下走
#(3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
#(4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
#(5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
# {'ip1':[时间1,时间2,时间3], 'ip2':[时间1,时间2]}
class MyThrottles():
VISIT_RECORD = {}
def __init__(self):
self.history=None
def allow_request(self,request, view):
#(1)取出访问者ip
# print(request.META)
ip=request.META.get('REMOTE_ADDR')
import time
ctime=time.time()
# (2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问
if ip not in self.VISIT_RECORD:
self.VISIT_RECORD[ip]=[ctime,]
return True
self.history=self.VISIT_RECORD.get(ip)
# (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
while self.history and ctime-self.history[-1]>60:
self.history.pop()
# (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
# (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
if len(self.history)<3:
self.history.insert(0,ctime)
return True
else:
return False
def wait(self):
import time
ctime=time.time()
return 60-(ctime-self.history[-1])

drf认证、权限、限流的更多相关文章

  1. 三 drf 认证,权限,限流,过滤,排序,分页,异常处理,接口文档,集xadmin的使用

    因为接下来的功能中需要使用到登陆功能,所以我们使用django内置admin站点并创建一个管理员. python manage.py createsuperuser 创建管理员以后,访问admin站点 ...

  2. day74:drf:drf其他功能:认证/权限/限流/过滤/排序/分页/异常处理&自动生成接口文档

    目录 1.django-admin 2.认证:Authentication 3.权限:Permissions 4.限流:Throttling 5.过滤:Filtering 6.排序:OrderingF ...

  3. django-rest-framework-源码解析004-三大验证(认证/权限/限流)

    三大验证模块概述 在DRF的APIView重写的dispatch方法中,  self.initial(request, *args, **kwargs) 这句话就是执行三大验证的逻辑, 点进去可以看到 ...

  4. (四) DRF认证, 权限, 节流

    一.Token 认证的来龙去脉 摘要 Token 是在服务端产生的.如果前端使用用户名/密码向服务端请求认证,服务端认证成功,那么在服务端会返回 Token 给前端.前端可以在每次请求的时候带上 To ...

  5. DRF 认证 权限 视图 频率

    认证组件 使用:写一个认证类,继承BaseAuthentication 在类中写authenticate方法,把request对象传入 能从request对象中取出用户携带的token根据token判 ...

  6. 45.限流Throttling及源码解析

    什么是限流? 限流类似于权限机制,它也决定是否接受当前请求,用于控制客户端在某段时间内允许向API发出请求的次数,也就是频率 假设有客户端(比如爬虫程序)短时间发起大量请求,超过了服务器能够处理的能力 ...

  7. drf 认证、权限、限流、过滤、排序、分页器

    认证Authentication 准备工作:(需要结合权限用) 1. 需要使用到登陆功能,所以我们使用django内置admin站点并创建一个管理员. python manage.py creates ...

  8. 2. DRF 认证、权限、限流、分页、过滤、序列 化

    2.1 user/urls.py   ModelViewSet注册路由三部曲 from django.urls import include, path from user import views ...

  9. drf06 认证Authentication 权限Permissions 限流Throttling

    为了方便接下来的学习,我们创建一个新的子应用 four python manage.py startapp four 因为接下来的功能中需要使用到登陆功能,所以我们使用django内置admin站点并 ...

随机推荐

  1. vtk网格剖分

    #include <vtkSmartPointer.h> #include <vtkSimplePointsReader.h> #include <vtkPolyData ...

  2. 面试突击32:为什么创建线程池一定要用ThreadPoolExecutor?

    在 Java 语言中,并发编程都是依靠线程池完成的,而线程池的创建方式又有很多,但从大的分类来说,线程池的创建总共分为两大类:手动方式使用 ThreadPoolExecutor 创建线程池和使用 Ex ...

  3. docker-compose.yml 版本问题

    Docker Engine 与docker-compose version 之间的有以下关系: Compose file format Docker Engine 1 1.9.0+ 2.0 1.10. ...

  4. 关于linux下的open()write()read()close()函数

    http://blog.sina.com.cn/s/blog_71d1a98701010s0v.html 1.read和write函数调用时,都会记录下当前写的位置,下次调用时就会从这个位置开始读或写 ...

  5. MYSQL5.7详细安装步骤

    0.更换yum源 1.打开 mirrors.aliyun.com,选择centos的系统,点击帮助 2.执行命令:yum install wget -y 3.改变某些文件的名称 mv /etc/yum ...

  6. 【freertos】002-posix模拟器设计与cortex m3异常处理

    目录 前言 posix 标准接口层设计 模拟器的系统心跳 模拟器的task底层实质 模拟器的任务切换原理 cortex M3/M4异常处理 双堆栈指针 双操作模式 栈帧 EXC_RETURN 前言 如 ...

  7. C++ 关于map,function的简单应用

    map<string,function<int(int, int)>> funs =    {        {"+", add},        {&qu ...

  8. leedCode

    https://blog.csdn.net/code_yilia/category_9851007.html https://blog.csdn.net/qq_17550379/article/det ...

  9. setTimeout时间延迟为何不准?

    单线程, 先执行同步主线程, 再执行异步任务队列

  10. JSP的常用指令有哪些?

    <% @ page %>  <% @ include %> <% @ taglib %>