drf框架之权限认证功能
一.项目背景引入
本人学习的是某马的前后端分离的美多商城项目,本项目中使用了权限认证。但项目中虽然实现了权限的动态分配以及添加,但在访问视图时没有做权限判定,没有实际功能,所以本人基于自定义权限后对其进行改进。
二.drf框架权限认证的介绍
drf和django对权限认证做了很好的封装,我们只需要很少的代码就可以实现RBAC(Role-Based Access Control的缩写,意为:基于权限的角色管理系统)。
用户模型类项目采用的是django自带的模型类,并对其进行了一定的继承和改进。
要了解用户权限,先来看看典型的权限六表
从上表我们可以看出,一个用户拥有的权限是他所在组的权限以及自身额外权限的相加。我们可以在后台项目中使用drf框架中的view和serializer快速对权限表进行增删改查。主要是修改组权限表和用户权限表,从而实现用户权限的动态处理
为了方便理解,再对各个表进行讲解
auth_group 存放你所创建的所有用户组
auth_permission存放所有的权限(自己生成的)一种一个模型类对应3个权限,可以自定义,content_type_id 指的是那个子应用的那个模型类
auth_group_permission 存放的是每个组拥有什么样的权限
tb_user 就是所有的用户
tb_user _group 就是用户属于你所创建的哪个组
tb_users_user_permission 就是该用户所有的额外权限
某马实现权限分配的页面展示
三.某马项目中对权限的处理
#!/usr/bin/env python
# -- coding: utf-8 --
# @Author : 宇智波---郭少
# @File : specs.py
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from django.contrib.auth.models import Permission, ContentType
from rest_framework.permissions import IsAdminUser
from meiduo_admin.serialziers.permissions import PerssionsSerialzier, ContentTypeSerialzier
from meiduo_admin.utils import PageNum
class PermissionsView(ModelViewSet):
serializer_class = PerssionsSerialzier
queryset = Permission.objects.all()
pagination_class = PageNum
permission_classes = [IsAdminUser]
# 父类中没有权限类型表的操作,需要自己封装方法
def content_type(self, request):
"""
获取权限类型
:param request:
:return:
"""
# 1、获取权限类型的所有数据
data = ContentType.objects.all()
# 2、序列化返回权限类型 self.get_serializer() 获取serializer_class属性所指定的序列器对象
ser = ContentTypeSerialzier(data, many=True) # 初始化生成序列化器对象
return Response(ser.data)
项目中采用的是权限的局部定义,这样每个视图都有自己的权限更加灵活
权限定义的代码是 permission_classes = [IsAdminUser]
查看源码
class IsAdminUser(BasePermission):
"""
Allows access only to admin users.
"""
def has_permission(self, request, view):
return bool(request.user and request.user.is_staff)
阅读源码发现只要访问这个视图的用户is_staff字段为true即可访问该视图。而在项目中我们可以登录后台的条件也是is_staff=true,这样我们在权限管理界面对用户组和用户分配的权限将没有任何意义。我们想实现的功能是超级管理员对用户权限分配后,只有拥有该权限的用户才可以看到对应的数据。
四.权限改进
在视图访问之前,自定义用户权限,当用户拥有改权限。才可以访问
# -- coding: utf-8 --
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from rest_framework.permissions import IsAuthenticated, BasePermission
from django.contrib.auth.models import Group, Permission
from meiduo_admin.serialziers.group import GroupSerialzier
from meiduo_admin.serialziers.permissions import PerssionsSerialzier
from meiduo_admin.utils import PageNum
#自定义用户权限
class MyPermission(BasePermission):
def has_permission(self, request, view):
user = request.user
if user.has_perm('add_group'):
return True
class GroupView(ModelViewSet):
# 父类方法需要调用序列化器
serializer_class = GroupSerialzier
# 视图集属性
queryset = Group.objects.all().order_by('id')
# 分页属性
pagination_class = PageNum
# 权限属性
permission_classes = [IsAuthenticated, MyPermission]
# @action(methods=['get'],detail=False) # methods指定方法所对应的请求方式 detail指定在生成的路径中是否需要正则匹配
def simple(self, request):
"""
获取权限数据
:param request:
:return:
"""
# 1、查询权限表
data = Permission.objects.all()
# 2、返回权限数据
ser = PerssionsSerialzier(data, many=True)
return Response(ser.data)
通过检验用户权限来判定是否返回数据,效果展示
进一步改进:
但在实际操作中我们还可以根据用户权限动态实现侧边栏的展示。先留个坑,下个项目本人前端使用的是vue-template-admin后端采用def来实现这一功能。
五麦