python Django权限控制之rbac应用源码

一、权限管理的访问控制

一、权限管理的访问控制
  权限管理,一般指控制用户的访问权限,使得用户可以访问而且只能访问自己被授权的资源,不能多也不能少。现在的软件系统里基本上都用到了权限管理,只是控制的粒度、层面和侧重点会有所不同,比较完善的权限管理包括四个方面的访问控制:

1.功能(最基础):以用户完成某一功能为准。如“添加用户”、“删除用户”

2.数据:比功能访问权限的控制粒度更小,如“管理员可看到比一般用户更多的信息”

3.时间:给访问权限添加时间控制,让访问的资源在某一时间段中可用。如”12306只能在7:00-23:00时间段内购票“

4.空间:给访问权限添加空间控制,根据访问用户的空间位置不同,而对用户的访问资源进行限制。如”很多人都在问,为什么在中国上不了facebook……“

二、RBAC设计理念

2.1.RBAC模型概述

RBAC模型(Role-Based Access Control:基于角色的访问控制)模型是20世纪90年代研究出来的一种新模型。RBAC认为权限授权的过程可以抽象地概括为:Who是否可以对What进行How的访问操作,并对这个逻辑表达式进行判断是否为True的求解过程

2.2 RBAC的组成

在RBAC模型里面,有3个基础组成部分,分别是:用户、角色和权限
RBAC通过定义角色的权限,并对用户授予某个角色从而来控制用户的权限,实现了用户和权限的逻辑分离(区别于ACL模型),极大地方便了权限的管理

下面在讲解之前,先介绍一些名词:

User(用户):每个用户都有唯一的UID识别,并被授予不同的角色
Role(角色):不同角色具有不同的权限
Permission(权限):访问权限
用户-角色映射:用户和角色之间的映射关系
角色-权限映射:角色和权限之间的映射
在这里插入图片描述
在这里插入图片描述

2.3 RBAC设计理念

RBAC的功能模块在这里插入图片描述
RBAC数据库设计在这里插入图片描述


二、Pyhton中RBAC的设计思路

1、数据库层面(models)

用户、角色、权限、权限组、菜单(菜单只是为了在页面展示以及菜单作用)

2、中间件层(middlewares)

中间件层是在用户请求服务器最前面的一层过滤系统,在rbac组件中它的作用是:

a、让未登录的用户无法访问相应的URL地址。 (用户登录之后 才能拥有特定权限,并且把相关权限格式化成字典格式 存入session)

b、把当前登录的用户权限和当前URL匹配 是否有权限,如果没有就返回404。

3、view视图层(view)

处理:路由系统分配的请求。

4、HTML层(前端页面显示)

三、代码

models.py

from django.db import models

class User(models.Model):
    phone = models.CharField(verbose_name="手机号码", max_length=11)
    user_name = models.CharField(verbose_name="姓名", max_length=30)
    user_code = models.CharField(verbose_name="账号", max_length=30)
    password = models.CharField(verbose_name="密码", max_length=30)
    status_cd = models.CharField(verbose_name="状态", max_length=10)
    create_date = models.DateTimeField(verbose_name="创建时间", max_length=30)
    roles = models.ManyToManyField(verbose_name="拥有的所有角色", to='Role', blank=True)

    def __str__(self):
        return self.user_name


class Role(models.Model):
    role_code = models.CharField(verbose_name="角色编码", max_length=30)
    role_name = models.CharField(verbose_name="角色名称", max_length=50)
    status_cd = models.CharField(verbose_name="状态", max_length=10)
    create_date = models.DateTimeField(verbose_name="创建时间", max_length=30)
    privileges = models.ManyToManyField(verbose_name="拥有的所有权限", to='Privilege', blank=True)

    def __str__(self):
        return self.role_name


class Privilege(models.Model):
    pri_code = models.CharField(verbose_name="权限编码", max_length=30)
    pri_name = models.CharField(verbose_name="权限名称", max_length=50)
    is_menu = models.BooleanField(verbose_name="是否可以做菜单", default=False)
    icon = models.CharField(verbose_name="图标", max_length=32, null=True, blank=True)
    status_cd = models.CharField(verbose_name="状态", max_length=10)
    create_date = models.DateTimeField(verbose_name="创建时间", max_length=30)

    def __str__(self):
        return self.pri_name

service 文件 init_privileges.py

from django.conf import settings


def init_privileges(current_user, request):
    """
    用户权限的初始化
    :param current_user: 当前用户对象
    :param request: 请求相关所有数据
    :return:
    """
    # 2. 权限信息初始化
    # 根据当前用户信息获取此用户所拥有的所有权限,并放入session。
    # 当前用户所有权限
    privileges_queryset = current_user.roles.filter(privileges__isnull=False).values('privileges__pri_code',
                                                                                     'privileges__pri_name').distinct()
   
    privileges_list = [item['privileges__pri_code'] for item in privileges_queryset]

    # for item in privileges_list:
    #     print(item)

    request.session[settings.PERMISSION_SESSION_KEY] = privileges_list

middleware.py

from django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixin
from CustomerNetwork import settings
import re


class checkPermission(MiddlewareMixin):

    def process_request(self, request):
        '''
         获取当前用户信息
         获取所有权限
         匹配
        '''
        current_url = request.path_info

        permission_dict = request.session.get(settings.PERMISSION_SESSION_KEY)
        if not permission_dict:
            return HttpResponse('无权限信息,请重新登录')

        for url in permission_dict:
            if re.match(current_url, url):
                # print(current_url)
                # print(url)
                return HttpResponse("ok1")

        # flag = False

views文件夹中.py

from django.shortcuts import render, HttpResponse

from rbac import models
from rbac.service.init_privilage import init_privileges


def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')
    user_name = request.POST.get('user')
    password = request.POST.get('pwd')
    current_user = models.User.objects.filter(user_name=user_name, password=password).first()  # 重复的第一个
    if not current_user:
        return render(request, 'login.html', {
    
    'msg': "用户名或密码错误"})
    init_privileges(current_user, request)
    return HttpResponse("ok")

template文件夹中html

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <form method="post">
        {
    
    % csrf_token %}
        <input type="text" name="user" placeholder="请输入用户名">
        <input type="password" name="pwd" placeholder="请输入密码">
        <input type="submit" value="提交"><span style="color: red">{
    
    {
    
     msg }}</span>
    </form>
</body>
</html>

settting.py

# 权限配置

PERMISSION_SESSION_KEY = "pri_session_key"

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',
    'webboss.md.middleware.checkPermission'
]

猜你喜欢

转载自blog.csdn.net/qq_35911309/article/details/109855694