DRF的权限组件(源码分析)
DRF的权限组件(源码分析)
1. 创建用户表
from django.db import models
# Create your models here.
class UserInfo(models.Model):
role_choice = ((1, 'CEO'), (2, 'CTO'), (3, 'CFO'))
role = models.SmallIntegerField(verbose_name='类型', choices=role_choice, default=1)
username = models.CharField(verbose_name='用户名', max_length=32)
password = models.CharField(verbose_name='密码', max_length=32)
token = models.CharField(verbose_name='TOKEN', max_length=64, null=True, blank=True)
2. 自定义权限类
from rest_framework.permissions import BasePermission
class PermissionA(BasePermission):
message = {'code': 1003, 'data': '无权访问'}
def has_permission(self, request, view):
if request.user.role == 2:
return True
return False
def has_object_permission(self, request, view, obj):
return True
3. 视图函数中添加认证
- 局部配置(views.py)
class UserView(APIView):
permission_classes = [PermissionA, ] # role权限
def get(self, request):
...
- 全局配置(settings.py)
REST_FRAMEWORK = {
# 权限
"DEFAULT_PERMISSION_CLASSES": ["app01.permission.PermissionA", ]
}
4. 多个权限类
当开发过程中需要用户同时具备多个权限(缺一不可)时,可以用多个权限类来实现。
权限组件内部处理机制:按照列表的顺序逐一执行 has_permission
方法,如果返回True,则继续执行后续的权限类;如果返回None或False,则抛出权限异常并停止后续权限类的执行。
# models.py
from django.db import models
class Role(models.Model):
""" 角色表 """
title = models.CharField(verbose_name="名称", max_length=32)
class UserInfo(models.Model):
""" 用户表 """
username = models.CharField(verbose_name="用户名", max_length=32)
password = models.CharField(verbose_name="密码", max_length=64)
token = models.CharField(verbose_name="TOKEN", max_length=64, null=True, blank=True)
roles = models.ManyToManyField(verbose_name="角色", to="Role")
# urls.py
from django.urls import path, re_path, include
from app01 import views
urlpatterns = [
path('api/auth/', views.AuthView.as_view()),
path('api/order/', views.OrderView.as_view()),
]
# views.py
import uuid
from rest_framework.views import APIView
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.authentication import BaseAuthentication
from rest_framework.permissions import BasePermission
from rest_framework.exceptions import AuthenticationFailed
from app01 import models
class AuthView(APIView):
""" 用户登录认证 """
def post(self, request, *args, **kwargs):
print(request.data) # {"username": "wupeiqi", "password": "123"}
username = request.data.get('username')
password = request.data.get('password')
user_object = models.UserInfo.objects.filter(username=username, password=password).first()
if not user_object:
return Response({"code": 1000, "data": "用户名或密码错误"})
token = str(uuid.uuid4())
user_object.token = token
user_object.save()
return Response({"code": 0, "data": {"token": token, "name": username}})
class TokenAuthentication(BaseAuthentication):
def authenticate(self, request):
token = request.query_params.get("token")
if not token:
raise AuthenticationFailed({"code": 1002, "data": "认证失败"})
user_object = models.UserInfo.objects.filter(token=token).first()
if not user_object:
raise AuthenticationFailed({"code": 1002, "data": "认证失败"})
return user_object, token
def authenticate_header(self, request):
return 'Bearer realm="API"'
class PermissionA(BasePermission):
message = {"code": 1003, 'data': "无权访问"}
def has_permission(self, request, view):
exists = request.user.roles.filter(title="员工").exists()
if exists:
return True
return False
def has_object_permission(self, request, view, obj):
return True
class PermissionB(BasePermission):
message = {"code": 1003, 'data': "无权访问"}
def has_permission(self, request, view):
exists = request.user.roles.filter(title="主管").exists()
if exists:
return True
return False
def has_object_permission(self, request, view, obj):
return True
class OrderView(APIView):
authentication_classes = [TokenAuthentication, ]
permission_classes = [PermissionA, PermissionA]
def get(self, request, *args, **kwargs):
return Response({"code": 0, "data": {"user": None, 'list': [1, 2, 3]}})
class PayView(APIView):
authentication_classes = [TokenAuthentication, ]
permission_classes = [PermissionA, ]
def get(self, request, *args, **kwargs):
return Response({"code": 0, "data": "数据..."})
5. 关于has_object_permission
后期补充...
6. 源码分析
第三步前面的部分执行流程和前两篇文章是一样的. 这里就不过多赘述了
本文来自博客园,作者:{Max},仅供学习和参考
posted on 2023-04-21 15:23 huxiaofeng 阅读(31) 评论(0) 编辑 收藏 举报