Django如何创建一套接口级别的权限系统

从零开始搭建当然是可以的,但是Django的特色就是大而全,所以,我的方案是,利用现有的Django框架,实现功能。
我用的pycharm,操作很方便快捷。

| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| django_content_type        |

先看看你的数据库,这些表,就是咱们创建权限系统会使用的所有数据表了,都是自动生成的,少哪个,自己百度去
想了解模型类,需要看源码。
源码如何查看方便?找到你的代码,随便找个地方,引用一下:

from django.contrib.auth.models import Permission

ctrl+鼠标左键,点击Permission,然后在打开的源码页面,上边的页面标签(auth/models.py)那里,右键,copy path,使用pycharm,点file,open,粘贴,删除粘贴字符串里面最后的“/models.py”,

... .../site-packages/django/contrib/auth

OK,open in new windows,OK,进去之后,像进入一个项目一样,这样非常有利于你了解源码。
如何快速了解一个Django项目?进去先看models。
如何一目了然的查看一个.py文件的结构?点pycharm的view,tool windows,structure,把一级标题都折叠起来!

现在,c 图标开头的,都是类,f 图标开头的都是函数。

update_last_login
PermissionManager
Permission
GroupManager
Group
UserManager
_user_get_all_permissions
_user_has_perm
_user_has_module_perms
PermissionsMixin
AbstractUser
User
AnonymousUser

百度翻译一下,了解这些类都是什么。不要全扔百度翻译,要先分词:

  • PermissionManager许可经理
  • Permission
    n.允许;批准,正式认可,认可
  • manager
    n.处理者,经理,管理人;干事,理事;
    〈美〉(政党等的)领袖;策士,干才,干练的人

显然差别很大。
manager结尾的(PermissionManager),是模型管理器类,和他前面一样的(Permission),是模型类。其他也是。

Permission
Group
User

这三个类,就是咱们需要仔细了解的,干货!
看看他的字段,还有他的父类的字段
Permission:

content_type = models.ForeignKey(
        ContentType,
        models.CASCADE,
        verbose_name=_('content type'),
    )

所以,你想创建权限,需要有对应的ContentType。
再去看看ContentType类,方法同上,ctrl+左键追踪源代码,复制路径,pycharm打开,了解一下。

class ContentType(models.Model):
    app_label = models.CharField(max_length=100)
    model = models.CharField(_('python model class name'), max_length=100)

就是字面意思,app名字和model名字。但是他的数据是根据你迁移时候,自动生成的,不是关联的。这意味着,咱们也可以,手动添加。
随便找个你项目里面的app,在admin.py里面加上

from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType

@admin.register(Permission)
class CompanyAdmin(admin.ModelAdmin):
    list_display = ('id','name','content_type','codename')

@admin.register(ContentType)
class CompanyAdmin(admin.ModelAdmin):
    list_display = ('id','app_label','model')

然后,打开django自带的后台,/admin,就可以看到这两个模型类:
Django如何创建一套接口级别的权限系统_第1张图片
如果groups和users没有,自己百度去,差不多的,应该。

  1. 然后创建一个自定义的ContentType,保存;
  2. 创建一个新的Permission,其中外键取刚刚创建的ContentType,其他先随便写上点什么显眼的字符。
  3. 这样就有权限了,可以给groups和users分配刚刚创建的新权限。
    现在咱们实现了权限的创立,下一步需要把他绑定到每一个接口上面,使客户端访问每一个接口时,都会检查一下权限。
    如果你django使用的视图类,就ctrl+左键追踪视图类的父类,
from rest_framework.views import APIView

APIView里面的

    def initial(self, request, *args, **kwargs):
        """
        Runs anything that needs to occur prior to calling the method handler.
        """
        self.format_kwarg = self.get_format_suffix(**kwargs)

        # Perform content negotiation and store the accepted info on the request
        neg = self.perform_content_negotiation(request)
        request.accepted_renderer, request.accepted_media_type = neg

        # Determine the API version, if versioning is in use.
        version, scheme = self.determine_version(request, *args, **kwargs)
        request.version, request.versioning_scheme = version, scheme

        # Ensure that the incoming request is permitted
        self.perform_authentication(request)
        self.check_permissions(request)
        self.check_throttles(request)

这个的意思是,initial初始化的时候,会走这几步。咱们创建一个APIView的子类,把check_permissions重写一下,然后,需要检查接口权限的视图类,直接继承这个新写的CheckPermissionView,就可以完成,每个接口都检测是否拥有权限的需求。

class CheckPermissionView(AllowAnyView):
    def check_permissions(self, request):
        # print(request.path_info)       
        # print(self.__class__.__name__)
        codename = request.path_info.split("/")[1] + "/" + self.__class__.__name__
        # print(codename)        # app_name/view_class_name        
        if codename[0] == "/":
            codename = "swagger"       
        user_id = request.user.id
        # print('user_id '*30)
        # print(user_id)
        if not user_id:
            raise BusinessException("请登录之后再访问此接口")
        group = Group.objects.filter(permissions__codename=codename,user__id=user_id).first()
        if not group:
            raise BusinessException("你的权限不足以访问此接口,若有需要,请联系管理员开通权限")

BusinessException是一个自定义错误,继承自Exception,这里不多说,不会写的,百度一下。
至于权限名字是如何定义的,你把我的注释打开,打印出来,就知道了。
一个接口对应一个权限,可以把一堆接口权限,都分给一个新创建的groups,然后,需要这些权限的users,直接加入groups,就可以轻松实现,接口粒度的权限管理。
全程代码不多,但是需要对源码有一定程度的理解,其他就是填权限麻烦一点点(当然可以使用SQL直接插入数据库,我感觉这样快一点点。SQL直接代码操作,生成还是很快的。不用挨个填admin后台)。
如果我的文章,对你有一点点帮助的话,请帮忙在右边小心心那里点赞一下,码字不易,也是为了将来找工作好找一点,O(∩_∩)O谢谢!

你可能感兴趣的:(django)