RBAC权限管理基本概念与实现

基于 Django 的后台管理平台,采用 RBAC 权限管理机制

  1. 用户表、角色表、权限表、资源列表

    1. 用户表 :账号、姓名、邮箱、添加时间、最后登录时间、账号是否禁止登录
    2. 角色表 :商品管理员、订单管理员、超级管理员
    3. 资源列表(路径正则) :资源名称(项目模块名称),资源路径(后台路由)
      1. 资源分类:商品模块、订单模块、营销模块、权限模块、内容模块、其他模块
    4. 权限表 :对某一个路由的增删改查权限
    5. ![QQ截图20201112161853](C:UserswyxDesktop小实训day13 RBAC角色权限管理路径接口图片QQ截图20201112161853.png)

    6. request返回

      1. ['DATA', 'FILES', 'POST', 'QUERY_PARAMS', '__class__', '__delattr__', '__dict__',
        '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattr__',
        '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__',
        '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__',
        '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__',
        '__subclasshook__', '__weakref__', '_auth', '_authenticate', '_authenticator',
        '_content_type', '_data', '_default_negotiator', '_files', '_full_data',
        '_load_data_and_files', '_load_stream', '_not_authenticated', '_parse',
        '_request', '_stream', '_supports_form_parsing', '_user', 'accepted_media_type',
        'accepted_renderer', 'auth', 'authenticators', 'content_type', 'data',
        'force_plaintext_errors', 'negotiator', 'parser_context', 'parsers',
        'query_params', 'stream', 'successful_authenticator', 'user', 'version',
        'versioning_scheme']
        
  2. RBAC角色权限管理机制实现思路

    • # 面向资源编程
      https://www.shiyanlou.com/v1/books/ # 请求后端 books书籍表中数据
              get
              post
              # 用户表
              # 角色表
              # 权限表
      get/post/put/delete 对应关系
      
    • 所有权限的本质是对数据库中表中数据增删改查的操作

    • 而这些增删改查的操作是通过前端不同路由,通过get、post、put、delete方法操作数据库的

    • 对权限的控制,最简单的方法就是判断当前用户是否可以对指定路由请求操作的权限

    • 把角色和这个角色能够访问的 url 和 请求方式进行关联(因为正是的业务逻辑用户权限划分力度可 能非常细致)

    • 再简单的业务逻辑中这一张表就是权限表

    • ![QQ截图20201112162121](C:UserswyxDesktop小实训day13 RBAC角色权限管理路径接口图片QQ截图20201112162121.png)

      • 后端如何判断用户权限
        1. 用户发送求方法 https://www.shiyanlou.com/v1/books/ 的url
        2. 后端首先查询时哪一个用户,然后查询当前用户的角色
        3. 最后判断这个角色是否可以访问 https://www.shiyanlou.com/v1/books/ 的对应方法即可
        4. 如果这个角色有权限访问这个url就返回数据,不能访问就返回 401状态码

重写django权限

  1. syl/utils/authentication.py 重写权限模块

    • """
      author:翔翔
      date:
      use:
      """
      from rest_framework.permissions import BasePermission
      from rest_framework import exceptions
      import re
      
      from course.models import UserCourse
      # 自定义权限(局部)
      
      
      class MyPermission(BasePermission):
          # has_permission 是用户对这个视图有没有 GET POST PUT PATCH DELETE 权限的分别判断
          def has_permission(self, request, view):
              print('has_perm')
              # print(view.kwargs.get("pk"), request.user.id)
              """判断用户对模型有没有访问权"""
              # 任何用户对使用此权限类的视图都有访问权限
              if request.user.is_superuser:
                  # 管理员对用户模型有访问权
                  return True
              elif view.kwargs.get('pk') == str(request.user.id):
                  # 携带的id和用户的id相同时有访问权
                  return True
              return False
      
          # has_object_permission 是用户过了 has_permission 判断有权限以后,再判断这个用户有没有对一个具体的对象有没有操作权限
          # 这样设置以后,即使是django admin管理员也只能查询自己user标的信息,不能查询其他用户的 单条信息
          def has_object_permission(self, request, view, obj):
              # 判断当前用户是否有访问 /course/sections/1/ 接口权限
              course_detail_url = re.match('/course/sections/(d+)/$', request.path_info)
              if course_detail_url:
                  user = request.user
                  course = obj.chapters.course
                  has_video_rights = self.video_rights(user, course)
                  return has_video_rights
              return True
              # 对用户是否有课程播放权限进行验证
      
          @staticmethod
          def video_rights(user, course):
      
              '''
              :param user: 当前登录用户
              :param course: 用户要播放的课程对象
              :return: 返回True有权限,否则出发异常
              '''
              # 1.免费课程直接返回True
              # 2.会员免费课程,判断当前用户是否是会员,如果是会员返回True
              # 3.付费课程,判断当前用户在UserCourse表中有购买记录返回True
              try:
                  is_buy = UserCourse.objects.get(course=course, user=user)
                  return True
              except Exception as e:
                  raise exceptions.ParseError('没卖课程播放个毛线!头给你打扁!')
      
      
  2. 添加视频播放接口权限

    1. course/urls.py 中添加路由

      1. router.register(r'sections', vi   ews.SectionsViewSet)
        
  3. course/views.py中使用自定义权限

    1. from utils.authentication import MyPermission
      class SectionsViewSet(viewsets.ModelViewSet):
          queryset = Sections.objects.all()
          serializer_class = SectionsSerializer
          permission_classes = (MyPermission,)
      
原文地址:https://www.cnblogs.com/wyx-zy/p/14012656.html