django framework权限增删改查细粒控制

一直想写restframework 系列教程
在restframwork中,结合django的原生类,使用django的原生类AbstractUser,我一开始的时候很排斥使用这个类,总想着不继承这个类自己写,但是多次使用自己写的发现问题很多,很多方法都无法使用,例如request.user这个就自己写的类无法继承使用,很烦,最后放弃了使用原生类

使用restframework自带网页展示和postman,可以很直观的让我们了解到restframework权限展示

通过访问http://192.168.56.104:8000/admin/auth/permission/
这个页面可以看到我们的每一个model在创建之后都默认赋予了can add,can delete,can view,can change四个功能,
在这里插入图片描述
在restframework网页中展示就是http://192.168.56.104:8000/goods/
在这里插入图片描述
上面这个图片属于增加can add功能权限
下面为delete,update,select 权限
在这里插入图片描述
上述登录用户为超级账号,增删改查权限都有
下面我们限制下
在这里插入图片描述
设置一个角色没有修改用户的权限
在这里插入图片描述通过restframework可以看到该用户的确没有修改用户的权限
在这里插入图片描述
具体这些权限怎么实现的,其实framework已经给出了答案
在项目的settings.py文件中设置restframework相关参数

REST_FRAMEWORK = {
       'DEFAULT_AUTHENTICATION_CLASSES':(
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        # 'utils.auth.JwtAuthorization',

),
    'DEFAULT_PERMISSION_CLASSES': (
        # 'rest_framework.permissions.IsAuthenticatedOrReadOnly',
        'utils.permissions.ModelPermission',
        # 'rest_framework.permissions.IsAuthenticated',
        # 'utils.permissions.IsOwnerOrReadOnly',
    ),
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',),

     'PAGE_SIZE': 10
}

我们使用的是’utils.permissions.ModelPermission’自己写的权限认证,只要使用继承使用restframework相关类的都会经过这个脚本文件的过滤,如果不适用restframework类的这个文件不起作用
贴出’utils.permissions.ModelPermission’的关键过滤代码

from .jwt_auth import  parse_payload



class ModelPermission(DjangoModelPermissions):
    def __init__(self):
        self.perms_map['GET'] = ['%(app_label)s.view_%(model_name)s']
    def has_permission(self, request, view):
        # print(request.path_info)
        # print(request.user,request.user.is_anonymous)
        queryset = self._queryset(view)
        model_cls = queryset.model
        # print(model_cls)
        kwargs = {
            'app_label': model_cls._meta.app_label,
            'model_name': model_cls._meta.model_name
        }

        list1=[perm % kwargs for perm in self.perms_map['OPTIONS']]
        # print(list1)
        # print(request.user)
        if request.user.is_anonymous:
            token = request.META.get('HTTP_AUTHORIZATION', '')
            user=parse_payload(token)
            request.user=user

        res=request.user.roles.values_list('permissions__permission__content_type__app_label','permissions__permission__codename')
        # print(res)
        perm_list=['.'.join(i) for i in res if i[0]!=None]
        # print(perm_list)
        queryset = self._queryset(view)
        perms = self.get_required_permissions(request.method, queryset.model)
        # print("长度是",len([item for item in perms if item not in perm_list]))
        return  len([item for item in perms if item not in perm_list])==0

if request.user.is_anonymous:
token = request.META.get(‘HTTP_AUTHORIZATION’, ‘’)
user=parse_payload(token)
request.user=user
这句话的含义是如果使用vue前端过来的用户,对里面的token值进行解析获取到真实的user信息,这一篇暂时不做介绍,后续写vue请求的时候在做处理。这样设置的目的是为了方便vue过来的请求和restframework自带网页过来的请求稍微对get请求做了重写,因为djangomodels的系统权限是can_view权限,所以我们要改写下
return len([item for item in perms if item not in perm_list])==0
这一句表达的含义是如果请求的访问权限不在用户的范围之内,那么就是false,前端无法进行访问也不会展示出来,例如上图的update权限就不能显示
贴出相关的models设计表

from django.db import models

# Create your models here.

from django.contrib.auth.models import AbstractUser,Permission
class User(AbstractUser):
    mobile=models.CharField(max_length=100,verbose_name='手机号码')
    address=models.CharField(max_length=200,verbose_name='居住地址')
    superior = models.ForeignKey("self", null=True, blank=True, verbose_name="上级主管",on_delete=models.CASCADE)
    roles = models.ManyToManyField("role", verbose_name="角色", blank=True)
    

    class Meta:
        verbose_name = "用户信息"
        verbose_name_plural = verbose_name
        ordering = ['id']

    def __str__(self):
        return self.username




class Menu(models.Model):
    """
    菜单
    """
    name = models.CharField(max_length=30, unique=True, verbose_name="菜单名")  # unique=True, 这个字段在表中必须有唯一值.
    parent = models.ForeignKey("self", null=True, blank=True, verbose_name="父菜单",on_delete=models.CASCADE)
    icon = models.CharField(max_length=50, null=True, blank=True, verbose_name="图标")
    oprtype=models.CharField(max_length=100,null=True,blank=True,verbose_name='操作类别')
    code = models.CharField(max_length=50, null=True, blank=True, verbose_name="编码")
    type=models.IntegerField(null=True,blank=True,choices=((0,'目录'),(1,'菜单'),(2,'按钮'),((3,'API接口'))),verbose_name='菜单类别')
    permission=models.ForeignKey(Permission,null=True,blank=True,verbose_name='对应自带权限表对应权限',on_delete=models.CASCADE)
    def __str__(self):
        return self.name

    class Meta:
        verbose_name = '菜单'
        verbose_name_plural = verbose_name

    @classmethod
    def get_menu_by_request_url(cls, url):
        return dict(menu=Menu.objects.get(url=url))


class Role(models.Model):
    """
    角色:用于权限绑定
    """
    name = models.CharField(max_length=32, unique=True, verbose_name="角色")
    permissions = models.ManyToManyField("menu", blank=True, verbose_name="菜单授权")
    desc = models.CharField(max_length=50, blank=True, null=True, verbose_name="描述")
    def __str__(self):
        return self.name
    class Meta:
        verbose_name = '角色'
        verbose_name_plural = verbose_name

以上为权限管理系统的实现部分代码,主要是继承了DjangoModelPermissions这个类,可以细粒化对orm model的增删改查

  • 技术无止境
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值