• Python Day 78 Django RBAC 基于角色访问控制


      ##RBAC

    RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联。简单地说,一个用户拥有若干角色,一个角色拥有若干权限。这样,就构造成“用户-角色-权限”的授权模型。在这种模型中,用户与角色之间,角色与权限之间都是多对多的关系。
    
    
    #注意:
    django在查找模板和静态文件的时候 如果全局没有不会直接报错而是去每一个应用下找templates以及static文件夹 所以能正常引入,这就是django基于应用开发的好处

      ##基于角色访问控制案例如下

      ##在app01应用中创建三张模型表

    from django.db import models
    
    # Create your models here.
    
    class User(models.Model):
        username = models.CharField(max_length=32)
        password = models.CharField(max_length=32)
        roles = models.ManyToManyField(to='Role')
    
        def __str__(self):
            return self.username
    class Role(models.Model):
        title = models.CharField(max_length=32)
        permissions = models.ManyToManyField(to='Permission')
        def __str__(self):
            return self.title
    class Permission(models.Model):
        title = models.CharField(max_length=32)
        url = models.CharField(max_length=255)
        def __str__(self):
            return self.title

      ##引入已经配置好的stark组件完成RBAC,该stark组件功能类似于django自带默认的admin功能

      ##在settings中配置stark应用

      ##在app01应用中创建stark.py文件,然后注册模型表

    from stark.service.stark import site,ModelStark
    from app01 import models
    
    
    site.register(models.User)
    site.register(models.Role)
    site.register(models.Permission)

      ##登录功能

    #login.html
    {% extends 'stark/base.html' %}
    
    
    {% block content %}
        <form action="" method="post">
        <h2 class="text-center">登录</h2>
        {% csrf_token %}
        <p>username:<input type="text" class="form-control" name="username"></p>
        <p>password:<input type="password" class="form-control" name="password"></p>
            <input type="submit" class="btn btn-info pull-right">
        </form>
    {% endblock %}
    
    #后端
    def login(request):
    
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
            user_obj = models.User.objects.filter(username=username,password=password).first()
            if user_obj:
                #记录当前用户状态
                request.session['username'] = user_obj.username
                #获取当前用户访问权限,还要去重
                permission_list = user_obj.roles.values('permissions__url').distinct()
                # print(permission_list) #<QuerySet [{'permissions__url': '/stark/app01/user/'}, {'permissions__url': '/stark/app01/role/'}]>
                #将当前访问的用户保存到session中
                request.session['permission_list'] = [permission.get('permissions__url') for permission in permission_list]
                return render(request,'index.html',locals())
        return render(request,'login.html')
    View Code

      ##中间件功能:登陆权限验证、黑白名单、url访问权限控制

    #setting中中间件配置
    MIDDLEWARE = [
           'app01.permission.permission.MyPermission',
    ]

      ###配置中间件 C:CRMapp01permissionpermission.py

    import re
    
    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import redirect,HttpResponse
    
    
    class MyPermission(MiddlewareMixin):
        def process_request(self,request):
            #获取当前用户像访问的url
            # print(request.path) #获取url后缀
            # print(request.get_full_path()) #获取后缀加get请求参数
            current_path = request.path
    
            #定义网站白名单,还有给以admin打头的全部通过'/admin/.*'
            white_list = ['/login/','/register/','/index/','/admin/.*']
            # if current_path in white_list:
            #     return None  #判断不太完美 有正则还是要通过正则来匹配
            for url in white_list:
                res = re.search(url,current_path)
                if res:
                    return None
    
            #校验用户是否登录
            if not request.session.get('username'):
                return redirect('/login')
    
            #校验用户权限
            permission_list = request.session.get('permission_list')
            #判断当前url是否在授权访问的url范围内
            """
                需要考虑的点:url中存在正则匹配,所以要比对存不存在,必须要通过正则来判断存不存在
                不能直接通过in来判断
            """
            for permission in permission_list:
                #固定授权的url,超过该url长度的不能通过匹配
                """
                 如:只能查看 http://127.0.0.1:8000/stark/app01/user/
                      每个他授权添加的话就不能匹配到添加url:
                        http://127.0.0.1:8000/stark/app01/user/add/
                """
                permission = '^%s$'%permission
                res = re.search(permission,current_path)
                if res :
                    return None
            return HttpResponse('没有权限')

      ##需求:给侧边栏展示用户的所有权限(一般只展示查询,编辑和添加没有意义)

    问题:怎么解决哪一个url是查询url,哪一个是编辑或者添加的url
    解决方案:通过给权限便permission添加一个flag字段来进行标识,查询url就标识list查询,添加就表示add,编辑就表示edit,删除就用delete来表示
            后端通过获取这个字段来查询哪些是查询url,然后添加到一个列表套字典形式的变量中,渲染给前端来使用该变量
  • 相关阅读:
    考察数据结构(An Extensive Examination of Data Structures)
    考察数据结构——第一部分:数据结构简介[译]
    老生常谈
    使用DataSet的ReadXml和WriteXml方法
    要掌握Sql Server,我还差得远啊!
    新浪短信Web Service
    还是水晶报表
    两种报表组件的功能分析
    无限级分类(非递归算法/存储过程版/GUID主键)完整数据库示例_(4)显示记录
    c#方法中调用参数的值传递方式和引用传递方式,以及ref与out的区别
  • 原文地址:https://www.cnblogs.com/liangzhenghong/p/11329512.html
Copyright © 2020-2023  润新知