认证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. 使用Docker 部署MongoDB

    使用 Docker 部署 MongoDB 查看官网安装教程后感觉直接使用包管理器安装mongo比较复杂,本文主要介绍使用docker安装部署mongo的方法,并对基本配置项进行自定义.保姆式全程指导. ...

  2. 自定义 Django admin 组件

    摘要:学习 Django admin 组件,仿照源码的逻辑,自定义了一个简易的 stark 组件,实现类似 admin 的功能. 可自动生成 url 路由,对于model 有与之相应的配置类对象,可进 ...

  3. CVE-2015-1427(Groovy 沙盒绕过 && 代码执行漏洞)

    1.vulhub环境搭建 https://blog.csdn.net/qq_36374896/article/details/84102101 2.启动docker环境 cd vulhub-maste ...

  4. synchronized 与 lock锁的异同

    相同点: 二者都可以解决线程安全问题: 不同点: 1..Synchronized 是Java内置的关键字:Lock是一个Java类: 2.Synchronized 无法判断锁的状态:Lock可以判断是 ...

  5. 什么是B+树??

    上一篇中,我们了解了B树,辣么..B+树又是什么呢?? 一:定义:B+树是基于B树的,是B树的变形,也是一种多路搜索树.查询性能更加出色. 1.每个父节点元素出现在子节点中,是子节点的最大或最小元素. ...

  6. @Required 注解?

    这个注解表明bean的属性必须在配置的时候设置,通过一个bean定义的显式的属性值或通过自动装配,若@Required注解的bean属性未被设置,容器将抛出BeanInitializationExce ...

  7. 哪些是重要的bean生命周期方法? 你能重载它们吗?

    有两个重要的bean 生命周期方法,第一个是setup , 它是在容器加载bean的时候被调用.第二个方法是 teardown  它是在容器卸载类的时候被调用. The bean 标签有两个重要的属性 ...

  8. centos容器安装nginx及运行

    进入centos容器: 安装依赖:yum insatll -y wget gcc gcc-c++ make openssl-devel 安装: 到官网复制下载链接:http://nginx.org/d ...

  9. 什么是基于 Java 的 Spring 注解配置?

    基于 Java 的配置,允许你在少量的 Java 注解的帮助下,进行你的大部分 Spring 配置而非通过 XML 文件. 以@Configuration 注解为例,它用来标记类可以当做一个 bean ...

  10. 什么是 Aspect?

    aspect 由 pointcount 和 advice 组成, 它既包含了横切逻辑的定义, 也包 括了连接点的定义. Spring AOP 就是负责实施切面的框架, 它将切面所定义的横 切逻辑编织到 ...