DRF-认证 权限 频率组件
补充
1 认证 权限 频率组件原理基本相同
2 认证相关:
session cookie token 认证相关的 这里用token
token 1 有时间限制,超时则失效 2 每次登录更换一个token
3 访问频率限制
1 防止同一时间多次访问的黑客攻击,增加服务器压力。
4 我们的解析 认证 权限 频率 是在用户get post等请求之前就做好了的
5 uuid随机数模块,uuid.uuid4()获取随机数
认证 权限 频率组件操作流程
认证需要建立user表和token表
# 用户表
class User(models.Model):
user=models.CharField(max_length=32)
pwd=models.CharField(max_length=32)
type=((1,"VIP"),(2,"SVIP"),(3,"SSSVIP"))
user_type=models.IntegerField(choices=type) # token表
class UserToken(models.Model):
user=models.OneToOneField("User")
token=models.CharField(max_length=128)
用户登录视图添加token
from app01.models import User,UserToken class LoginView(APIView):
"""
1000:成功
1001:用户名或者密码错误
1002:异常错误
"""
def post(self,request): response = {"code": 1000, "msg": None, "user": None}
try:
print(request.data)
user = request.data.get("user")
pwd = request.data.get("pwd") user = User.objects.filter(user=user, pwd=pwd).first()
import uuid
random_str = uuid.uuid4()
if user: UserToken.objects.update_or_create(user=user, defaults={"token": random_str})
response["user"] = user.user
response["token"] = random_str
else:
response["code"] = 1001
response["msg"] = "用户名或者密码错误" except Exception as e:
response["code"]=1002
response["msg"]=str(e) return Response(response)
认证自定义的模块
其中继承 BaseAuthentication除了类本生加的功能外还继承了header方法,如果不继承需要自己写一个header方法,否则会报错!
from app01.models import UserToken
from rest_framework.exceptions import AuthenticationFailed from rest_framework.authentication import BaseAuthentication class UserAuth(BaseAuthentication): def authenticate(self,request): token=request.query_params.get("token") usertoken=UserToken.objects.filter(token=token).first()
if usertoken:
return usertoken.user,usertoken.token
else:
raise AuthenticationFailed("认证失败!")
权限组件自定义的模块
from rest_framework.permissions import AllowAny class SVIPPermission(object):
message="您没有访问权限!"
def has_permission(self,request,view):
if request.user.user_type >= 2:
return True
return False
频率组件自定义的模块
以一分钟访问3次为例
from rest_framework.throttling import BaseThrottle
VISIT_RECORD={}
class VisitThrottle(BaseThrottle):
def __init__(self):
self.history=None
def allow_request(self,request,view):
remote_addr = request.META.get('REMOTE_ADDR')
print(remote_addr)
import time
ctime=time.time()
if remote_addr not in VISIT_RECORD:
VISIT_RECORD[remote_addr]=[ctime,]
return True
history=VISIT_RECORD.get(remote_addr)
self.history=history
while history and history[-1]<ctime-60:
history.pop()
if len(history)<3:
history.insert(0,ctime)
return True
else:
return False
def wait(self):
import time
ctime=time.time()
return 60-(ctime-self.history[-1])
在全局中的定制
REST_FRAMEWORK={
# 解析器组件
'DEFAULT_PARSER_CLASSES': (
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
),
# 认证组件
'DEFAULT_AUTHENTICATION_CLASSES': (
'app01.utils.auth_class.UserAuth',
),
# 权限组件
'DEFAULT_PERMISSION_CLASSES': (
'app01.utils.permission_class.SVIPPermission',
),
# 频率组件
'DEFAULT_THROTTLE_CLASSES': (),
}
在局部中的定制及在视图中的使用
# 导入自定义的认证功能类
from app01.utils.auth_class import UserAuth
# 导入自定义的权限功能类
from app01.utils.permission_class import SVIPPermission
# 导入自定义的频率功能类
from app01.utils.throttle_classes import VisitThrottle from rest_framework.throttling import BaseThrottle
class VisitThrottle(BaseThrottle):
def allow_request(self,request,view):
"""
限制IP每分钟访问不能超过3次
:param request:
:param view:
:return:
"""
print(self.get_ident(request))
remote_addr = request.META.get('REMOTE_ADDR')
print("REMOTE_ADDR",remote_addr)
return False class BookView(APIView):
# 认证
# authentication_classes = [UserAuth]
# 权限
# permission_classes = [SVIPPermission]
# 频率
throttle_classes = [VisitThrottle] def get(self,request):
'''
查看所有书籍
:param request:
:return:
''' print(request.user,request.auth) book_list=Book.objects.all()
serializer=BookSerializer(book_list,many=True)
return Response(serializer.data) def post(self,request):
'''
添加一条书籍
:param request:
:return:
'''
print(request.data) serializer=BookSerializer(data=request.data,many=False) if serializer.is_valid():
serializer.save() # create操作 return Response(serializer.data)
else:
return Response(serializer.errors) class SBookView(APIView): def get(self,request,id):
edit_obj=Book.objects.get(pk=id)
serializer=BookSerializer(edit_obj,many=False)
return Response(serializer.data) def put(self,request,id):
edit_obj = Book.objects.get(pk=id)
serializer=BookSerializer(data=request.data,instance=edit_obj)
if serializer.is_valid():
serializer.save() # edit_obj.update(request.data)
return Response(serializer.data)
else:
return Response(serializer.errors) def delete(self,request,id):
edit_obj = Book.objects.get(pk=id).delete()
return Response("")
以认证为例的源码解析
//用户访问,当经过dispath时
1 def dispatch(self, request, *args, **kwargs):
self.initial(request, *args, **kwargs)
initial()是我们的解析 认证 权限 频率功能
2 在initial函数中
def initial(self, request, *args, **kwargs):
# 执行认证功能
self.perform_authentication(request)
# 执行权限功能
self.check_permissions(request)
# 执行频率功能
self.check_throttles(request)
3 我们走perform_authentication(request)认证功能
def perform_authentication(self, request):
request.user
从这里我们要从request实例中找user方法
4 我们通过request实例对象找到它的类中的user方法
def dispatch(self, request, *args, **kwargs):
request = self.initialize_request(request, *args, **kwargs)
def initialize_request(self, request, *args, **kwargs)
return Request(
request,
parsers=self.get_parsers(),
authenticators=self.get_authenticators(),
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)
class Request(object):
def user(self):
if not hasattr(self, '_user'):
with wrap_attributeerrors():
self._authenticate()
return self._user
5 在_authenticate()中:
def _authenticate(self):
# 和解析器一样,获得[UserAuth()] 获得顺序:当前视图类下-->全局setting-->默认default
for authenticator in self.authenticators:
try:
# 执行authenticate方法进行验证,返回元组/空 或抛出一个异常
user_auth_tuple = authenticator.authenticate(self)
except exceptions.APIException:
self._not_authenticated()
raise
# 如果返回一个元组则执行下面的语句
if user_auth_tuple is not None:
self._authenticator = authenticator
self.user, self.auth = user_auth_tuple
# 这里有个坑,如果返回元组,则直接结束_authenticate函数,不继续循环了!
return
这里如果不抛异常则进入下一个组件
DRF-认证 权限 频率组件的更多相关文章
- 实战-DRF快速写接口(认证权限频率)
实战-DRF快速写接口 开发环境 Python3.6 Pycharm专业版2021.2.3 Sqlite3 Django 2.2 djangorestframework3.13 测试工具 Postma ...
- restful知识点之三restframework认证-->权限-->频率
认证.权限.频率是层层递进的关系 权限业务时认证+权限 频率业务时:认证+权限+频率 局部认证方式 from django.conf.urls import url,include from djan ...
- 8) drf 三大认证 认证 权限 频率
一.三大认证功能分析 1)APIView的 dispath(self, request, *args, **kwargs) 2)dispath方法内 self.initial(request, *ar ...
- DRF 认证 权限 视图 频率
认证组件 使用:写一个认证类,继承BaseAuthentication 在类中写authenticate方法,把request对象传入 能从request对象中取出用户携带的token根据token判 ...
- rest framework 认证 权限 频率
认证组件 发生位置 APIview 类种的 dispatch 方法执行到 initial 方法 进行 认证组件认证 源码位置 rest_framework.authentication 源码内部需要 ...
- (四) DRF认证, 权限, 节流
一.Token 认证的来龙去脉 摘要 Token 是在服务端产生的.如果前端使用用户名/密码向服务端请求认证,服务端认证成功,那么在服务端会返回 Token 给前端.前端可以在每次请求的时候带上 To ...
- 三 drf 认证,权限,限流,过滤,排序,分页,异常处理,接口文档,集xadmin的使用
因为接下来的功能中需要使用到登陆功能,所以我们使用django内置admin站点并创建一个管理员. python manage.py createsuperuser 创建管理员以后,访问admin站点 ...
- Django rest_framework----认证,权限,频率组件
认证 from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions impor ...
- rest-framework框架——认证、权限、频率组件
一.rest-framework登录验证 1.models.py添加User和Token模型 class User(models.Model): name = models.CharField(max ...
随机推荐
- 解决django的后台管理界面添加中文内容乱码问题
在使用django migrate功能时,默认数据库的字符集不是utf8. 是latin 1,然后在后台管理model时,不允许有中文字符插入 解决方案: 在使用migrate建库之前先把数据库建立起 ...
- 关于C#7 新语法糖
C#7新语法糖 1.Switch 使用 goto 使用 ; switch (kk) { : Console.WriteLine(); ; : Console.WriteLine(); ; : Con ...
- 箭头函数的arguments不可用
ES5中的arguments function func(a,b,c){ console.log(arguments[0],arguments[1],arguments[2]) } func(1,2, ...
- MySQL 的COUNT(x)性能怎么样?
做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! x 可以代表: 主键id.字段.1.* 0 说明 对于count(主键id)来说 innodb引擎会遍历整张表,把每一行的 ...
- Node初始以及环境搭建(Node01)
1. 相关概念 •什么是JavaScript? •一种遵守ECMAScript标准的脚本语言 •最初只能运行在浏览器端 •浏览器中的 JavaScript 可以做什么? •操作DOM:表单验证.动画 ...
- C# Winform 设置窗口打开的特效
https://www.cnblogs.com/mq0036/p/6421946.html using System.Runtime.InteropServices; public class Win ...
- 把zTree前的展开收起图标改为三角形,且只有在点击三角形图标时才展开子节点解决方案
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta ht ...
- React/动态绑定class
第一种 字符串拼接 <i className={["iconfont"+" "+item.icon]} ></i> 第二种 有判断条件的 ...
- LINUX安装Tree软件包
1.将镜像光盘放入光驱中 查看当前LINUX版本号:cat /etc/redhat-release 2.挂载镜像文件 mount /dev/cdrom /mnt mount :挂载设备命令 /d ...
- MySQL授权(用户权限)
一.mysql查询与权限 (二)授权 用户管理: 设置用户密码 前期准备工作: 停止服务 将配置文件当中的skip-grant-tables删除掉 重启服务: 执行修改命令 查看用户状态(如果数据过多 ...