【django之權限組件】

1、需求分析

RBAC(Role-Based Access Control,基於角色的訪問控制),就是用戶經過角色與權限進行關聯。簡單地說,一個用戶擁有若干角色,一個角色擁有若干權限。這樣,就構形成「用戶-角色-權限」的受權模型。在這種模型中,用戶與角色之間,角色與權限之間都是多對多的關係。css

一個可訪問的含正則表達式的url就是一個權限,利用角色控制訪問url。html

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

 

三、登陸驗證

將登陸用戶的全部權限信息注入到session中數據庫

rbac/service/initail.pydjango

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

 

四、基於中間件作權限校驗

功能:  1.白名單驗證;bootstrap

     2.驗證是否已經寫入session,即:是否已經登陸;session

     3.當前訪問的url與當前用戶的權限url進行匹配驗證,並在request中寫入code信息app

 

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.pyide

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("無權訪問")

 

3、代碼

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
相關文章
相關標籤/搜索