Django REST Framework 认证 - 权限 - 限制
2024-08-29 00:56:33
一. 认证
(你是谁?)
REST framework 提供了一些开箱即用的身份验证方案,并且还允许你实现自定义方案。
自定义Token认证
第一步 : 建表>>>>
定义一个用户表和一个保存用户Token的表
class UserInfo(models.Model):
username = models.CharField(max_length=16)
password = models.CharField(max_length=32)
type = models.SmallIntegerField(
choices=((0, '普通用户'), (1, 'VIP用户')),
default=0
) class Token(models.Model):
user = models.OneToOneField(to='UserInfo')
token_code = models.CharField(max_length=128)
第二步: 定义一个登陆视图 >>>>
from rest_framework.views import APIView
from app2 import models
from rest_framework.response import Response
import hashlib, time def get_random_token(username):
"""
根据用户名和时间戳生成随机token
"""
timestamp = str(time.time())
m = hashlib.md5(bytes(username, encoding="utf-8"))
m.update(bytes(timestamp, encoding="utf-8"))
return m.hexdigest() class LoginView(APIView):
"""
校验用户名是否正确从而生成token的视图
"""
def post(self, request):
res = {"code": 0}
# print(request.data)
username = request.data.get("username")
password = request.data.get("password") user = models.UserInfo.objects.filter(username=username, password=password).first()
if user:
token = get_random_token(username)
models.Token.objects.update_or_create(defaults={"token_code": token}, user=user)
res["token"] = token
else:
res["code"] = 1
res["error"] = "用户名或密码错误"
return Response(res)
第三步: 定义一个认证类 >>>>
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from app2 import models class MyAuth(BaseAuthentication):
def authenticate(self, request):
# if request.method in ["POST", "PUT", "DELETE"]: # 如果在表单中需要判断请求方式 由于表单是post请求,所以获取token 的方式为 request.data.get("token")
# request.query_params为url中的参数
request_token = request.query_params.get("token", None)
if not request_token:
raise AuthenticationFailed('q.缺少token') token_obj = models.Token.objects.filter(token_code=request_token).first()
if not token_obj:
raise AuthenticationFailed("无效的Token")
# token_obj.user 通过token这张表的对象和user这个关联字段 找到 UserInfo表的对象及当前用户对象
return token_obj.user, request_token # else:
# return None, None
第四步: 使用认证类 >>>>
视图级别认证
class CommentViewSet(ModelViewSet): queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer
authentication_classes = [MyAuth, ]
全局级别认证
# 在settings.py中配置
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ]
}
二. 权限
(你能干什么?) 设置只有VIP才能看到的东西
第一步: 自定义一个权限类
"""
自己动手写一个权限组件
"""
from rest_framework.permissions import BasePermission class MyPermission(BasePermission): message = '只有VIP才能访问' def has_permission(self, request, view):
# 认证类中返回了token_obj.user, request_token
# request.auth 等价于request_token
if not request.auth:
return False
# request.user为当前用户对象
if request.user and request.user.type == 1: # 如果是VIP用户
print("requ", request.user, type(request.user))
return True
else:
return False
第二步: 使用
视图级别配置
class CommentViewSet(ModelViewSet): queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer
authentication_classes = [MyAuth, ]
permission_classes = [MyPermission, ]
全局级别设置
# 在settings.py中设置rest framework相关配置项
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],
"DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ]
}
三. 控制
(你一分钟能干多少次?)**好像有点污~~
第一步: 自定义限制类 >>>>
import time # from rest_framework.throttling import
visit_record = {} class MyThrottle(object): def __init__(self):
self.history = None def allow_request(self, request, view):
# 拿到当前的请求的ip作为访问记录的 key
ip = request.META.get('REMOTE_ADDR')
# 拿到当前请求的时间戳
now = time.time()
if ip not in visit_record:
visit_record[ip] = []
# 把当前请求的访问记录拿出来保存到一个变量中
history = visit_record[ip]
self.history = history
# 循环访问历史,把超过10秒钟的请求时间去掉
while history and now - history[-1] > 10:
history.pop()
# 此时 history中只保存了最近10秒钟的访问记录
if len(history) >= 3:
return False
else:
# 判断之前有没有访问记录(第一次来)
self.history.insert(0, now)
return True def wait(self):
"""告诉客户端还需等待多久"""
now = time.time()
return self.history[-1] + 10 - now # history = ['9:56:12', '9:56:10', '9:56:09', '9:56:08'] # '9:56:18' - '9:56:12' # history = ['9:56:19', '9:56:18', '9:56:17', '9:56:08'] # 最后一项到期的时间就是下一次允许请求的时间 # 最后一项到期的时间:now - history[-1] > 10 # 最后一项还剩多少时间过期
# history[-1] + 10 - now
第二步: 使用 >>>
视图中使用
class CommentViewSet(ModelViewSet): queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer
throttle_classes = [MyThrottle, ]
全局中使用
# 在settings.py中设置rest framework相关配置项
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],
"DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ]
"DEFAULT_THROTTLE_CLASSES": ["app01.utils.MyThrottle", ]
}
其实还可以使用内置限制类
from rest_framework.throttling import SimpleRateThrottle class VisitThrottle(SimpleRateThrottle): scope = "xxx" def get_cache_key(self, request, view):
return self.get_ident(request)
全局配置
# 在settings.py中设置rest framework相关配置项
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],
# "DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ]
"DEFAULT_THROTTLE_CLASSES": ["app01.utils.VisitThrottle", ],
"DEFAULT_THROTTLE_RATES": {
"xxx": "5/m",
}
}
看源码:
1.认证流程
2. 权限
最新文章
- Spark SQL 之 DataFrame
- 【HTML5】 web上的音频
- angular-ui-router中的$stateProvider设置
- Android搭建junit测环境
- 攻城狮在路上(叁)Linux(二十二)--- linux磁盘挂载与卸载 mount umount
- CPlus的简单线程的制作
- [NYIST32]组合数(状压,枚举,暴力)
- svn出错错误
- qml+opencv(二),实现人脸检测
- asp.net EF6.0中出现未找到具有固定名称“System.Data.SqlClient”的 ADO.NET提供程序的实体框架提供程序解决办法
- 用深度学习(DNN)构建推荐系统 - Deep Neural Networks for YouTube Recommendations论文精读
- 老帖收藏,留供参考:SpringMvc2.5+Mybatis3.2.7
- 剑指offer 10.递归和循环 矩形覆盖
- 前端-----JavaScript 初识基础
- Robotframework 3- 安装
- java高并发编程(三)
- Linux 双网卡配置两个IP同时只有一个会通的原因
- Python之分支结构
- 在 JS 对象中使用 . 和 [] 操作属性的区别
- Linux删除多余内核