• Django_rbac_demo 权限控制组件框架模型


    rbac 权限控制组件

    • 基于角色的权限控制
    • 本质每个权限即为一个 URL

    项目组件结构

    表结构

    Role (title, permission) -(ManyToManyField)-   User   (name, pwd, roles)  

         |                        

    (ManyToManyField)

         |                                 

    Permission (title, url)

     实际生成表 及 测试数据

    Django_rbac/ rbca/models.py

    from django.db import models
    
    # Create your models here.
    
    
    class User(models.Model):
        name = models.CharField(max_length=32)
        pwd = models.CharField(max_length=32)
        roles = models.ManyToManyField(to="Role")
    
        def __str__(self): return self.name
    
    
    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=32)
    
        def __str__(self):return self.title
    View Code

    核心代码部分

    Django_rbac/ rbac/service/permission.py 

      用于获取当前用户的权限信息

    """
    为了解耦,将处理权限的代码保存在组件里面
    """
    
    
    def initial_session(user,request):
        # 查看当前用户的所有的权限
        # 因为会有values 的原理会导致有重复需要去重
        ret = user.roles.all().values("permissions__url").distinct()
        permission_list = []
        # 将所有的权限保存在一个列表里面,稍微处理下数据便于操作
        for i in ret:
            permission_list.append(i["permissions__url"])
        # 把用户的用户权限保存在 session 里面
        request.session["permission_list"] = permission_list

    Django_rbac/rbac/service/rbca.py 

      基于当前用户的权限信息对来访请求进行逻辑判断筛选返回结果

        为了不冗余代码写在中间件中,对每一次的请求都做计算

        因中间件的工作机制导致所有的请求都被计算,需要对特殊的 URL 进行特殊处理

    import re
    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import HttpResponse, redirect
    """
    写在中间件里面可以完全避免每次都要重复校验的问题
    在请求来的时候进行校验,因此要写在 process_request 方法里面
    """
    
    
    class ValidPermission(MiddlewareMixin):
        def process_request(self,request):
            # 当前访问路径
            current_path = request.path_info
            """
            检查是否属于白名单
                admin 的内部流程 
                    不允许一上来就访问首页,必须要跳转到 登陆页面
                    http://127.0.0.1:8000/admin/login/?next=/admin/
                    第二次跳转到登录页面的请求如果没有被定义可通过就会被拦截
                    无法只使用 admin 为过滤选项
                    不能用 in 单纯的判断,还是要用到正则处理
                    需要放过所有 admin 开头的 url 
            """
            valid_url_list = ["/login/","/reg/","/admin/.*"]
            for valid_url in valid_url_list:
                ret = re.match(valid_url,current_path)
                if ret:
                    # 中间件 return None 表示这个中间件已经执行完毕
                    return None
    
            """
            校验是否登录
                对于没有登陆的用户返回报错应该是让他去登陆
            """
            user_id = request.session.get("user_id")
            if not user_id:
                return redirect("/login/")
    
            """
            校验权限
                在编辑,以及删除页面的时候 url 不是固定的,
                会有内含的参数,因此权限列表里面不能仅仅是写死的url
                也不能再单纯的用 in 来判断。还是要靠正则来处理
                将权限列表里面的权限信息用 正则表达式来保存
                然后对访问页面进行验证是否可以通过来处理
            """
            permission_list = request.session.get("permission_list",[]) 
            flag = False
            for permission in permission_list:
                permission = f"^{permission}$"
                ret = re.match(permission, current_path)
                if ret:
                    flag = True
                    break
            if not flag:
                return HttpResponse("没有访问权限! ")
            return None

       不要忘记注册在 Django_rbacDjango_rbacsettings.py 里面 

     

    其他app 引用使用

    Django_rbac/app01/views.py 

    from django.shortcuts import render,HttpResponse
    import re
    # Create your views here.
    from rbac.models import *
    from rbac.service.perssions import initial_session
    
    
    def users(request):
        user_list=User.objects.all()
        return render(request,"users.html",locals())
    
    
    def add_user(request):
        permission_list = request.session["permission_list"]
        return HttpResponse("add user.....")
    
    
    def roles(request):
        role_list=Role.objects.all()
        return render(request,"roles.html",locals())
    
    
    def login(request):
        if request.method == "POST":
            user = request.POST.get("user")
            pwd = request.POST.get("pwd")
            # 拿到当前用户对象
            user = User.objects.filter(name=user, pwd=pwd).first()
            if user:
                # 把用户的id 保存在 session 里面
                request.session["user_id"] = user.pk
                # 查询当前用户的所有的权限
                initial_session(user,request)
                return HttpResponse("登录成功!")
        return render(request, "login.html",locals())

    测试页面代码

      这个就比较随意了,看个结果而已。

    Django_rbac emplateslogin.html

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
    </head>
    <body>
    
    <h4>登录页面</h4>
    
    <form action="" method="post">
        {% csrf_token %}
        
        用户名:<input type="text" name="user">
        密码:<input type="password" name="pwd">
        <input type="submit">
    </form>
    
    
    </body>
    </html>
    View Code

    Django_rbac emplates oles.html

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
    </head>
    <body>
    
    <h4>角色列表</h4>
    <ul>
        {% for role in role_list %}
        <p>{{ role }}</p>
        {% endfor %}
    
    </ul>
    
    </body>
    </html>
    View Code

    Django_rbac emplatesusers.html

     1 <!DOCTYPE html>
     2 <html lang="zh-CN">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>Title</title>
     6     <meta name="viewport" content="width=device-width, initial-scale=1">
     7 </head>
     8 <body>
     9 
    10 <h4>用户列表</h4>
    11 <ul>
    12     {% for user in user_list %}
    13     <p>{{ user }}</p>
    14     {% endfor %}
    15 
    16 </ul>
    17 
    18 </body>
    19 </html>
    View Code
  • 相关阅读:
    最实用的logback讲解(2)—appender
    深入理解lombok
    idea(三)最值得安装的几款插件
    idea(二)初次安装强烈建议修改的配置
    swagger2的使用和swagger2markup离线文档的生成(最简单的方式)
    maven(一) 基础知识
    maven(二)pom文件详解
    ubuntu下jdk的安装
    maven(三)最详细的profile的使用
    profile之springboot
  • 原文地址:https://www.cnblogs.com/shijieli/p/10169263.html
Copyright © 2020-2023  润新知