1. 程式人生 > >rbac基於角色的許可權管理開發

rbac基於角色的許可權管理開發

一、model模組

許可權表結構設計:
許可權表結構設計

from django.db import models


class User(models.Model):
    """
    使用者表
    """
    username = models.CharField(verbose_name='使用者名稱', max_length=32)
    password = models.CharField(verbose_name='密碼', max_length=64)
    email = models.EmailField(verbose_name='郵箱')

    def
__str__(self):
return self.username class Role(models.Model): """ 角色表 """ caption = models.CharField(verbose_name='角色', max_length=32) def __str__(self): return self.caption class User2Role(models.Model): """ 使用者角色關係表 """ user = models.ForeignKey(User, verbose_name='使用者'
, related_name='roles',on_delete='') role = models.ForeignKey(Role, verbose_name='角色', related_name='users',on_delete='') def __str__(self): return '%s-%s' % (self.user.username, self.role.caption,) class Menu(models.Model): """ 選單表 """ caption = models.CharField(verbose_name='選單名稱'
, max_length=32) parent = models.ForeignKey('self', verbose_name='父選單', related_name='p', null=True, blank=True,on_delete='') def __str__(self): prev = "" parent = self.parent while True: if parent: prev = prev + '-' + str(parent.caption) parent = parent.parent else: break return '%s-%s' % (prev, self.caption,) class Permission(models.Model): """ 許可權 """ caption = models.CharField(verbose_name='許可權', max_length=32) url = models.CharField(verbose_name='URL正則', max_length=128) menu = models.ForeignKey(Menu, verbose_name='所屬選單', related_name='permissions',null=True,blank=True,on_delete='') def __str__(self): return "%s-%s" % (self.caption, self.url,) class Action(models.Model): """ 操作:增刪改查 """ caption = models.CharField(verbose_name='操作標題', max_length=32) code = models.CharField(verbose_name='方法', max_length=32) def __str__(self): return self.caption class Permission2Action2Role(models.Model): """ 許可權操作關係表 """ permission = models.ForeignKey(Permission, verbose_name='許可權URL', related_name='actions',on_delete='') action = models.ForeignKey(Action, verbose_name='操作', related_name='permissions',on_delete='') role = models.ForeignKey(Role, verbose_name='角色', related_name='p2as',on_delete='') class Meta: unique_together = ( ('permission', 'action', 'role'), ) def __str__(self): return "%s-%s-%s" % (self.permission, self.action, self.role,)

二、urls.py模組

urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^auth-login.html$', views2.login),
    url(r'^auth-index(-\d+)*.html$', views2.index),
]

三、views.py模組

from django.shortcuts import render,redirect,HttpResponse
from app02 import models

# Create your views here.
def login(request):
    if request.method == 'GET':
        return render(request, 'login2.html')
    else:
    #     # 根據使用者登入資訊獲得所有許可權
    #     object = models.User.objects.filter(username='tom').first()  # 假定根據登陸資訊獲得使用者名稱為tom
    #     # 根據使用者物件獲得對應的所有角色(有2種方式)
    #     role_list = models.User2Role.objects.filter(user_id=object.id)  # 方式一:正向操作 獲得[User2Role,User2Role,User2Role]
    #     # 方式二:反向操作,通過users跨表到user表中的user_id欄位,獲得對應的role表的所有id,從而獲得所有role(推薦該方法)
    #     role_list = models.Role.objects.filter(users__user_id=object.id)
    #
    #     # 根據角色物件,獲得所有許可權,並去重
    #     from django.db.models import Count
    #     # models.Permission2Action2Role.objects.filter(role__in=role_list).values('permission__url', 'action__code').annotate(c = Count('id'))
    #     # 推薦下面方式,不會生成新的欄位c
    #     permission_list = models.Permission2Action2Role.objects.filter(role__in=role_list).values('permission__url', 'action__code').distinct()
    #     # 獲得結果如下所示:
    #     """
    #     [
    #     {permission_url: '/index.html', action_code:'GET'},
    #     {permission_url: '/index.html', action_code:'POST'},
    #     {permission_url: '/index.html', action_code:'DEL'},
    #     {permission_url: '/index.html', action_code:'Edit'},
    #     {permission_url: '/order.html', action_code:'GET'},
    #     {permission_url: '/order.html', action_code:'POST'},
    #     {permission_url: '/order.html', action_code:'DEL'},
    #     {permission_url: '/order.html', action_code:'Edit'},
    # ]
    # """
        # 再通過for迴圈將資料庫中查出的資料轉換成如下格式:
        user_permission_dict = {
            '/ah-index.html': ["GET","POST","DEL","Edit"],
            '/order.html':  ["GET","POST","DEL","Edit"],
            '/auth-index(-\d+)*.html':  ["GET","POST","DEL","Edit"],  # 可接收通過格式 '/auth-index-3.html', '/auth-index.html'
        }

        # 將使用者的對應的許可權放入session中,當訪問其它連結時,可直接從session中進行校驗是否存在該許可權
        request.session['user_permission_dict'] = user_permission_dict
        return HttpResponse('登陸成功')

def index(request):
    return HttpResponse('登陸成功,你擁有了許可權,恭喜你看見了我')

三、html模版

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form method="POST" action="/auth-login.html">
    {% csrf_token %}
    <input type="text" name="user/">
    <input type="submit" value="提交/">
</form>
</body>
</html>

四、自定義中介軟體

# 新增中介軟體,控制權限
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
import re
class M1(MiddlewareMixin):
    def process_request(self, request, **kwargs):
        valid = ['/auth-login.html', '/index.html'] # 設定白名單,不進行校驗
        if request.path_info not in valid:  # /auth-index
            action = request.GET.get('md')   # 獲得操作指令
            user_permission_dict = request.session.get['user_permission_dict']  # 獲得許可權字典
            if not user_permission_dict:
                return HttpResponse('無許可權')

            flag = False
            if request.path_info != '/favicon.ico':   # 每一次請求,request.path_info會獲得兩個值,請求url和/favicon
                for k, v in user_permission_dict.items():
                    if re.match(k, request.path_info):  # 正則匹配,假定資料庫的為/index-(\d+).html,則/auth-index-3.html等格式可同樣包括
                        if action in v:
                            flag = True     # 表示該使用者擁有該許可權操作,繼續往下執行
                            break
                if not flag:
                    return HttpResponse('無許可權')

六、setting.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',
    'middleware.md.M1',   # 將該中介軟體註冊
]