参考博客:https://www.cnblogs.com/yuanchenqi/articles/8719520.html
一、权限组件
1.权限组件介绍
权限组件和认证组件的工作流程是基本相同的,可以参照 [Python自学] restframework (3) (认证组件) 中的流程。
2.为User表添加权限
# 用户表 class User(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=32) type_choices = ((1, "普通用户"), (2, "VIP"), (3, "SVIP")) # 默认用户类型都是普通用户 user_type = models.IntegerField(choices=type_choices, default=1)
执行命令:
python manage.py makemigrations
python manage.py migrate
3.实现权限验证类
在utils.py中实现:
# utils.py from rest_framework.permissions import BasePermission from .models import User class SVIPPermission(BasePermission): def has_permission(self, request, view): # 因为在验证token的时候,request.user已被赋值,所以可以从这里获取用户名 user = request.user # 获取该用户的用户类型 user_type = User.objects.filter(username=user.username).first().user_type if user_type == 3: return True # 如果权限正确,则通过 else: return False # 权限不正确,则验证失败
将其应用到某个视图类,例如AuthorViewSet:
from .utils import SVIPPermission class AuthorViewSet(viewsets.ModelViewSet): permission_classes = [SVIPPermission] queryset = Author.objects.all() serializer_class = AuthorModelSerializers
注意,在权限组件使用之前,应该还需要认证组件,这里的认证组件是在settings中配置的。
4.测试
使用Postman先登录,获取token:
{"code": 1000, "msg": null, "token": "81ba24601ce5be47ff2d96142a8ccb76"}
然后拿着token来获取books的数据:
[{"id":8,"publish":"http://127.0.0.1:8000/publishes/1/","title":"Python2标准库3","price":99,"pub_date":"2012-11-20T13:03:33Z","authors":[1,2]},{"id":9,"publish":"http://127.0.0.1:8000/publishes/1/","title":"Python2标准库4","price":99,"pub_date":"2012-11-20T13:03:33Z","authors":[1,2]},{"id":10,"publish":"http://127.0.0.1:8000/publishes/1/","title":"Python2标准库5","price":99,"pub_date":"2012-11-20T13:03:33Z","authors":[1,2]},{"id":11,"publish":"http://127.0.0.1:8000/publishes/1/","title":"Python2标准库6","price":99,"pub_date":"2012-11-20T13:03:33Z","authors":[1,2]},{"id":12,"publish":"http://127.0.0.1:8000/publishes/1/","title":"Python2标准库7","price":99,"pub_date":"2012-11-20T13:03:33Z","authors":[1,2]},{"id":13,"publish":"http://127.0.0.1:8000/publishes/1/","title":"Python2标准库","price":99,"pub_date":"2012-11-20T13:03:33Z","authors":[1,2]},{"id":14,"publish":"http://127.0.0.1:8000/publishes/1/","title":"Python3","price":99,"pub_date":"2020-01-20T13:03:04Z","authors":[3]},{"id":15,"publish":"http://127.0.0.1:8000/publishes/1/","title":"JAVA","price":99,"pub_date":"2020-01-20T13:03:04Z","authors":[3]},{"id":16,"publish":"http://127.0.0.1:8000/publishes/1/","title":"JAVA","price":99,"pub_date":"2020-01-20T13:03:04Z","authors":[3]},{"id":17,"publish":"http://127.0.0.1:8000/publishes/1/","title":"JAVA","price":99,"pub_date":"2020-01-20T13:03:04Z","authors":[3]},{"id":18,"publish":"http://127.0.0.1:8000/publishes/1/","title":"hello","price":99,"pub_date":"2020-01-20T13:03:04Z","authors":[3]}]
然后获取authors的数据:
{"detail":"You do not have permission to perform this action."}
由于leokale的用户类型是"普通用户",所以权限无法通过,则无法获取authors的数据。
修改detail提示信息:
class SVIPPermission(BasePermission): message = "只有超级用户才能访问" def has_permission(self, request, view): # 因为在验证token的时候,request.user已被赋值,所以可以从这里获取用户名 user = request.user # 获取该用户的用户类型 user_type = User.objects.filter(username=user.username).first().user_type if user_type == 3: return True # 如果权限正确,则通过 else: return False # 权限不正确,则验证失败
我们在数据库中将leokale用户的用户类型修改为"SVIP":
然后,再次获取authors的数据:
[{"id":1,"name":"leo","age":32},{"id":2,"name":"alex","age":35},{"id":3,"name":"Jone","age":23},{"id":5,"name":"李雷","age":90}]
成功获取到数据。
5.全局配置
和认证组件一样,如果想对所有视图类进行权限验证,也可以在settings中的REST_FRAMEWORK进行配置:
REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": ["demo.utils.TokenAuth"], "DEFAULT_PERMISSION_CLASSES":["demo.utils.SVIPPermission"] }
二、频率组件
1.频率组件介绍
频率组件用来控制单位时间的访问频率,如果超过访问次数,则不允许访问,例如1分钟20次。工作过程和认证组件以及权限组件都是一样的。
2.需要实现一个频率检测类
from rest_framework.throttling import BaseThrottle class VisitRateThrottle(BaseThrottle): def allow_request(self, request, view): # 这里判断是否超出频率阈值 # 例如以ip为键,判断某个ip在1分钟内的访问次数 # 或者以用户名为键 # 统计一分钟内的访问次数 stat = True if stat: return True else: return False
将其应用到某个视图类,例如AuthorViewSet:
class AuthorViewSet(viewsets.ModelViewSet): permission_classes = [SVIPPermission] throttle_classes = [VisitRateThrottle] queryset = Author.objects.all() serializer_class = AuthorModelSerializers
(¬‿¬)