• 【django之权限组件】


    一、需求分析

    RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联。简单地说,一个用户拥有若干角色,一个角色拥有若干权限。这样,就构造成“用户-角色-权限”的授权模型。在这种模型中,用户与角色之间,角色与权限之间都是多对多的关系。

    一个可访问的含正则表达式的url就是一个权限,利用角色控制访问url。

    二、功能实现

    1、目录树

    2、数据库设计

    用户组,角色,权限

    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("Role")
    
        def __str__(self):
            return self.name
    
    class Role(models.Model):
        title=models.CharField(max_length=32)
        permissions=models.ManyToManyField("Permission")
        def __str__(self):
            return self.title
    
    class Permission(models.Model):
        url=models.CharField(max_length=32)
        title=models.CharField(max_length=32,default="")
        p_group=models.ForeignKey("PermissionGroup",default=1)
        code=models.CharField(max_length=32,default="list",)
        def __str__(self):
            return self.title
    
    
    class PermissionGroup(models.Model):
        name=models.CharField(max_length=32)
        def __str__(self):
            return self.name
    models.py

    3、登录验证

    将登录用户的所有权限信息注入到session中

    rbac/service/initail.py

    def permission_session(user,request):
        # 将当前user的所有权限注入session中
    
        # 方式1:
        #permissions = user.roles.all().values("permissions__url").distinct()
        # permission_list = []
        # for i in permissions:
        #     permission_list.append(i.get("permissions__url"))
        #
        # request.session["permission_list"] = permission_list
    
        # 方式2:
        permissions = user.roles.all().values("permissions__url","permissions__p_group_id","permissions__code").distinct()
    
        # print(permissions)
    
        permission_dict={}
        for permission in permissions:
            p_group_id=permission.get("permissions__p_group_id")
    
            if p_group_id in permission_dict:
                permission_dict[p_group_id]["urls"].append(permission.get("permissions__url"))
                permission_dict[p_group_id]["codes"].append(permission.get("permissions__code"))
            else:
                permission_dict[p_group_id]={
                      "urls":[permission.get("permissions__url")],
                      "codes":[permission.get("permissions__code")],}
    
        print(permission_dict)
    
        request.session["permission_dict"]=permission_dict

    4、基于中间件做权限校验

    功能:  1.白名单验证;

         2.验证是否已经写入session,即:是否已经登录;

         3.当前访问的url与当前用户的权限url进行匹配验证,并在request中写入code信息

    settings.py

    MIDDLEWARE = [
    
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        "rbac.service.rbac.PermissionValid",
    
    ]

    rabc.py

    from django.utils.deprecation import MiddlewareMixin
    
    from django.shortcuts import HttpResponse,redirect,render
    
    class PermissionValid(MiddlewareMixin):
    
        def process_request(self,request):
    
            valid_url=["/login/","/reg/","/admin/.*"]      #白名单
            import re
            for url in valid_url:
                url="^%s$"%url
                ret=re.match(url,request.path_info)
                if ret:
                    return None
    
        #.验证是否已经写入session,即:是否已经登录
            if not request.session.get("user_id"):
                return redirect("/login/")
    
            current_path = request.path_info
    
            # 方式1:
            # permission_list = request.session.get("permission_list")
            #
            # import re
            #
            # flag = False
            # for permission in permission_list:
            #     permission="^%s$"%permission
            #     ret = re.match(permission, current_path)
            #     if ret:
            #         flag = True
            #         break
            # if not flag:
            #     return HttpResponse("无权访问")
    
            # 方式2:
    
        #与当前访问的url与权限url进行匹配验证,并在request中写入code信息,
            permission_dict = request.session.get("permission_dict")
    
            import re
    
            flag = False
            for item in permission_dict.values():
                urls=item["urls"]
    
                for permission in urls:
                     permission="^%s$"%permission
                     ret = re.match(permission, current_path)
                     if ret:
                        print("codes",item.get("codes"))
                        request.codes=item.get("codes")
                        return None
    
            return HttpResponse("无权访问")

    三、代码

    from django.shortcuts import render,HttpResponse,redirect
    
    # Create your views here.
    
    
    from rbac.models import *
    
    
    class PermissionCode(object):
        def __init__(self,codes):
            self.codes=codes
        def list(self):
             return "list" in self.codes
        def add(self):
             return "add" in self.codes
        def edit(self):
             return "edit" in self.codes
        def delete(self):
             return "del" in self.codes
    
    
    def users(request):
    
        user_list=User.objects.all()
    
        per=PermissionCode(request.codes)
    
    
        return render(request,"users.html",locals())
    
    def add_users(request):
    
        return HttpResponse("添加用户")
    
    def change_users(request,id):
    
        return HttpResponse("编辑用户")
    def delete_users(request,id):
    
        return HttpResponse("删除用户")
    
    
    
    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:
    
                request.session["user_id"]=user.pk
    
                from rbac.service.initail import permission_session
                permission_session(user,request)
    
                return HttpResponse("登录成功")
    
    
        return render(request,"login.html")
    app01/views.py
    def permission_session(user,request):
        # 将当前user的所有权限注入session中
    
    
    
    
        # 方式1:
        #permissions = user.roles.all().values("permissions__url").distinct()
        # permission_list = []
        # for i in permissions:
        #     permission_list.append(i.get("permissions__url"))
        #
        # request.session["permission_list"] = permission_list
    
        # 方式2:
        permissions = user.roles.all().values("permissions__url","permissions__p_group_id","permissions__code").distinct()
    
        # print(permissions)
    
        permission_dict={}
        for permission in permissions:
            p_group_id=permission.get("permissions__p_group_id")
    
            if p_group_id in permission_dict:
                permission_dict[p_group_id]["urls"].append(permission.get("permissions__url"))
                permission_dict[p_group_id]["codes"].append(permission.get("permissions__code"))
            else:
                permission_dict[p_group_id]={
                      "urls":[permission.get("permissions__url")],
                      "codes":[permission.get("permissions__code")],}
    
        print(permission_dict)
    
        request.session["permission_dict"]=permission_dict
    rabc/service/initail.py
    from django.utils.deprecation import MiddlewareMixin
    
    from django.shortcuts import HttpResponse,redirect,render
    
    class PermissionValid(MiddlewareMixin):
    
        def process_request(self,request):
    
            valid_url=["/login/","/reg/","/admin/.*"]      #白名单
            import re
            for url in valid_url:
                url="^%s$"%url
                ret=re.match(url,request.path_info)
                if ret:
                    return None
    
        #.验证是否已经写入session,即:是否已经登录
            if not request.session.get("user_id"):
                return redirect("/login/")
    
            current_path = request.path_info
    
            # 方式1:
            # permission_list = request.session.get("permission_list")
            #
            # import re
            #
            # flag = False
            # for permission in permission_list:
            #     permission="^%s$"%permission
            #     ret = re.match(permission, current_path)
            #     if ret:
            #         flag = True
            #         break
            # if not flag:
            #     return HttpResponse("无权访问")
    
            # 方式2:
    
        #与当前访问的url与权限url进行匹配验证,并在request中写入code信息,
            permission_dict = request.session.get("permission_dict")
    
            import re
    
            flag = False
            for item in permission_dict.values():
                urls=item["urls"]
    
                for permission in urls:
                     permission="^%s$"%permission
                     ret = re.match(permission, current_path)
                     if ret:
                        print("codes",item.get("codes"))
                        request.codes=item.get("codes")
                        return None
    
            return HttpResponse("无权访问")
    rabc/service/rabc.py
    from django.contrib import admin
    
    # Register your models here.
    
    from .models import *
    
    admin.site.register(User)
    admin.site.register(Role)
    
    
    class PermissionConfig(admin.ModelAdmin):
        list_display = ["title","url","p_group","code"]
    admin.site.register(Permission,PermissionConfig)
    admin.site.register(PermissionGroup)
    rabc/admin.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("Role")
    
        def __str__(self):
            return self.name
    
    class Role(models.Model):
        title=models.CharField(max_length=32)
        permissions=models.ManyToManyField("Permission")
        def __str__(self):
            return self.title
    
    class Permission(models.Model):
        url=models.CharField(max_length=32)
        title=models.CharField(max_length=32,default="")
        p_group=models.ForeignKey("PermissionGroup",default=1)
        code=models.CharField(max_length=32,default="list",)
        def __str__(self):
            return self.title
    
    
    class PermissionGroup(models.Model):
        name=models.CharField(max_length=32)
        def __str__(self):
            return self.name
    rabc/models.py
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'app01.apps.App01Config',
        "rbac.apps.RbacConfig",
    ]
    
    MIDDLEWARE = [
    
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        "rbac.service.rbac.PermissionValid",
    
    ]
    settings.py
    from django.conf.urls import url
    from django.contrib import admin
    
    from app01 import views
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^login/$', views.login),
        url(r'^users/$', views.users),
        url(r'^users/add/$', views.add_users),
        url(r'^users/(d+)/change/$', views.change_users),
        url(r'^users/(d+)/delete/$', views.delete_users),
    ]
    urls.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
    <form action="" method="post">
        {% csrf_token %}
        用户名:<input type="text" name="user">
        密码:<input type="text" name="pwd">
        <input type="submit">
    </form>
    
    
    </body>
    </html>
    templates/login.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    </head>
    <body>
    
    
    
    <div class="container">
        <h3>查看用户</h3>
    
       <div class="col-md-6">
           {% if per.add %}
                 <a href="/users/add/" class="btn btn-primary">添加用户</a>
           {% endif %}
    
            <table class="table table-borderd table-striped col-md-offset-4">
               {% for user in user_list %}
                   <tr>
                    <td>{{ forloop.counter }}</td>
                    <td>{{ user.name }}</td>
    
                     {% if per.edit %}
                         <td><a href="/users/{{ user.pk }}/change" class="btn btn-success">编辑</a></td>
                     {% endif %}
    
                     {% if per.delete  %}
                         <td><a href="/users/{{ user.pk }}/delete/" class="btn btn-success">删除</a></td>
                     {% endif %}
    
                   </tr>
                {% endfor %}
             </table>
       </div>
    </div>
    
    
    
    
    
    </body>
    </html>
    templates/users.html
  • 相关阅读:
    SQL盲注工具BBQSQL
    嗅探X-Windows服务按键工具xspy
    多协议底层攻击工具Yesinia
    LLMNR欺骗工具Responder
    Arduino可穿戴教程保存源文件与打开已经存在的源文件
    GRDB使用SQLite的WAL模式
    CString之GetBuffer与ReleaseBuffer
    VC++ 模块与资源分离
    KV6.60 SP1
    Html之head部分详解
  • 原文地址:https://www.cnblogs.com/smallmars/p/8695125.html
Copyright © 2020-2023  润新知