Django_rbac_demo 權限控制組件框架模型

rbac 權限控制組件

  • 基於角色的權限控制
  • 本質每一個權限即爲一個 URL

項目組件結構

表結構

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

     |                        正則表達式

(ManyToManyField)django

     |                                 session

Permission (title, url)app

 實際生成表 及 測試數據

Django_rbac/ rbca/models.pyide

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 post

  用於獲取當前用戶的權限信息測試

"""
爲了解耦,將處理權限的代碼保存在組件裏面
"""


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

  基於當前用戶的權限信息對來訪請求進行邏輯判斷篩選返回結果spa

    爲了避免冗餘代碼寫在中間件中,對每一次的請求都作計算

    因中間件的工做機制致使全部的請求都被計算,須要對特殊的 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_rbac\Django_rbac\settings.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\templates\login.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\templates\roles.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\templates\users.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
相關文章
相關標籤/搜索