权限管理笔记

一、把rbac组件拷贝到你的Django项目中

二、settings里注册一下app名字

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # 'web.apps.WebConfig',
    'web',
    'rbac',
]

 

三、python manage.py makemigrations 和 python manage.py migrate生成数据库表单

四、在settings里注册一下中间件,用来验证用户权限

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.middleware.rbac.RbacMiddleware'
]

 

五、在settings里最下方配置权限相关的信息

# ############################## RBAC权限相关配置开始 ##############################
# # 无需权限控制的URL(白名单)
RBAC_NO_AUTH_URL = [
    '/login.html',
    '/index.html',
    '/register.html',
    '/admin.*',
    '/rbac.*',
]

# session中保存权限信息的Key名
RBAC_PERMISSION_SESSION_KEY = "rbac_permission_session_key"

# Http请求中传入的参数,根据其获取GET、POST、EDIT等检测用户是否具有相应权限
# 例如:
#       http://www.example.com?md=get   表示获取
#       http://www.example.com?md=post  表示添加
#       http://www.example.com?md=del   表示删除
RBAC_QUERY_KEY = "md"
RBAC_DEFAULT_QUERY_VALUE = "look"

# 无权访问时,页面提示信息
RBAC_PERMISSION_MSG = "无权限访问"

# Session中保存菜单和权限信息的Key
RBAC_MENU_PERMISSION_SESSION_KEY = "rbac_menu_permission_session_key"
RBAC_MENU_KEY = "rbac_menu_key"
RBAC_MENU_PERMISSION_KEY = "rbac_menu_permission_key"

# 菜单主题
RBAC_THEME = "default"
# ############################## RBAC权限相关配置结束 ##############################

  

六、登录的页面login.html

在你应用的app的models.py中创建UserInfo一对一关联rabc里的User表

from django.db import models
from rbac.models import User as RbacUser
class UserInfo(models.Model):
    nickname = models.CharField(max_length=16)
    user = models.OneToOneField(RbacUser)
models.py

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login.html" method="POST">
    {% csrf_token %}
    <div><input type="text" name="username" id=""></div>
    <div><input type="password" name="passwd" id=""></div>
    <div><input type="submit" value="提交"></div>
</form>
</body>
</html>
login.html
from django.conf.urls import url
from django.contrib import admin
from web import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login.html', views.login),
    url(r'^index.html', views.index),
]
url配置
from django.shortcuts import render,HttpResponse,redirect
from web import models
def login(request):
    if request.method == 'GET':
        return render(request,'login.html')
    else:
        u = request.GET.get('username')
        p = request.GET.get('passwd')
        # 跨表到rbac的用户表里拿用户名和密码
        obj = models.UserInfo.objects.filter(user__username=u,user__password=p).first()
        # obj.id 是UserInfo表里的自增id
        # obj.nickname
        # obj.user_id 是rbac的User表里的用户id
        # obj.id和obj.user_id不一样
        if obj:# 表示用户存在,登录成功
         # 获取当前用户权限
         # 获取当前用用户菜单
         # 去配置文件里拿相应的key,写入session中
         # 在rbac组件的service.py中的initial_permission已经把上面的步骤都做好了,只需要传入参数request和obj.user_id
         from rbac.service import initial_permission
         initial_permission(request,obj.user_id)

         request.session['user_info'] = {'username':u,'nickname':obj.nickname,'nid':obj.id} # 添加一些自己的信息

         return redirect('/index.html')
        else:
            return render(request,'login.html')

 

中间件的函数

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import re
from django.conf import settings
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

class RbacMiddleware(MiddlewareMixin):
    def process_request(self, request, *args, **kwargs):
        """
        检查用户是否具有权限访问当前URL
        :param request: 
        :param args: 
        :param kwargs: 
        :return: 
        """
        """跳过无需权限访问的URL"""
        for pattern in settings.RBAC_NO_AUTH_URL:
            if re.match(pattern, request.path_info):
                return None

        """获取当前用户session中的权限信息"""
        permission_dict = request.session.get(settings.RBAC_PERMISSION_SESSION_KEY)
        if not permission_dict:
            # settings.RBAC_PERMISSION_MSG 返回错误信息:'无权限访问'
            return HttpResponse(settings.RBAC_PERMISSION_MSG)

        """当前URL和session中的权限进行匹配"""

        flag = False
        for pattern, code_list in permission_dict.items():
            upper_code_list = [item.upper() for item in code_list]  # 把方法列表都变成大写
            if re.match(pattern, request.path_info):                # 匹配可以访问的url和当前URL
                # settings.RBAC_QUERY_KEY是'md' ; 异常时默认拿到settings.RBAC_DEFAULT_QUERY_VALUE 即'GET'
                request_permission_code = request.GET.get(settings.RBAC_QUERY_KEY, settings.RBAC_DEFAULT_QUERY_VALUE).upper()
                if request_permission_code in upper_code_list:
                    request.permission_code = request_permission_code  # 当前的方法权限加入request
                    request.permission_code_list = upper_code_list     # 当前的方法权限列表加入request中
                    flag = True
                    break

        if not flag:
            # settings.RBAC_PERMISSION_MSG 返回错误信息:'无权限访问'
            return HttpResponse(settings.RBAC_PERMISSION_MSG)

  

在用户验证登录成功后跳转到index函数和index.html页面

CBV函数的写法

def index(request):
    # permission_code是在中间件的代码里获取的当前登录用户所请求的权限方法
    # request.permission_code 当前登录用户所请求的权限
    # request.permission_code_list 当前登录用户所具有的权限方法
    if request.permission_code == 'GET':
        # 查看权限
        pass
    elif request.permission_code == 'POST':
        # 增加权限
        pass
    elif request.permission_code == 'DEL':
        # 删除权限
        pass
    elif request.permission_code == 'EDIT':
        # 编辑权限
        pass
    return render(request,'index.html')

 

FBV中的写法

from django.views import View
from rbac.cbv.views import RbacView
# 用于Django视图CBV模式时,根据请求地址后携带md对应的值执行相应的方法,如:
class MyView(RbacView, View):
    def get(request, *args, **kwargs):
        pass

    def delete(request, *args, **kwargs):
        pass

    def put(request, *args, **kwargs):
        pass

    def post(request, *args, **kwargs):
        pass

# MyView类中方法的名称取决于数据库action表code字段的值。PS:此处方法为小写

 

在app的models中添加报障表

from django.db import models
from rbac.models import User as RbacUser
class UserInfo(models.Model):
    nickname = models.CharField(max_length=16)
    user = models.OneToOneField(RbacUser)

class Order(models.Model):
    nid = models.IntegerField(primary_key=True)
    """
    报障单
    """
    title = models.CharField(verbose_name='报障标题',max_length=64)
    detail = models.TextField(verbose_name='故障详细')
    create_user = models.ForeignKey(UserInfo,related_name='cre')
    create_time = models.DateTimeField()
    status_choice = (
        (1,'未处理'),
        (2,'处理中'),
        (3,'已处理'),
    )
    status = models.IntegerField(choices=status_choice,default=1)
    processor = models.ForeignKey(UserInfo,related_name='pro',null=True,blank=True)
    solution = models.TextField(null=True,blank=True)
    processor_time = models.DateTimeField()
View Code

然后python manage.py makemigrations 和 python manage.py migrate 生成一下,

 

报障管理

  普通员工

    提报障单    trouble.html

      创建

      修改

      删除

      查看列表

      查看详细

 

  运维人员

    解决报障单    trouble-kill.html

 

  总监

    提报障单

    解决报障单

    查看报表    report.html

先在admin里注册一下表单

from django.contrib import admin
from web import models

admin.site.register(models.UserInfo)
admin.site.register(models.Order)

  

用admin给rabc的User表添加数据

给Role表里添加三个角色:总监、运维、员工

然后User2Role分配一下用户是什么角色(一个用户可以有多个角色)

菜单添加一个保障管理即可

permission里添加权限名称:报障,URL正则:/trouble.html,所属菜单:报障管理

  权限名称:解决报障,URL正则:/trouble-kill.html,所属菜单:报障管理

  权限名称:查看报表,URL正则:/report.html,所属菜单:报障管理

 

action表中创建几个方法 post   del    edit    look    detail

permission2action2role 分配权限 员工拥有报障单的所有方法权限    运维拥有解决报障单的所有方法权限

 七、在index.html中导入自定义的simple_tag

{% load rbac %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        body{
            margin: 0;
        }
        .pd-header{
            height: 48px;
            background-color: brown;
        }
        .pd-menu{
            float: left;
            width: 20%;
        }
        .pd-content{
            float: left;
            width: 80%;
        }
        {% rbac_css %}
    </style>
</head>
<body>
    <div class="pd-header"></div>
    <div class="pd-body">
        <div class="pd-menu">{% rbac_menu request %}</div>
        <div class="pd-content">Welcome : {{ request.session.user_info.nickname }}</div>
    </div>
    <script src="/static/jquery-1.12.4.js"></script>
    <script>
        {% rbac_js %}
    </script>
</body>
</html>
index.html

 

创建母模layout.html

{% load rbac %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        body{
            margin: 0;
        }
        .pd-header{
            height: 48px;
            background-color: brown;
        }
        .pd-menu{
            float: left;
            width: 20%;
        }
        .pd-content{
            float: left;
            width: 80%;
        }
        {% rbac_css %}
    </style>
    {% block css %}{% endblock %}
</head>
<body>
    <div class="pd-header"></div>
    <div class="pd-body">
        <div class="pd-menu">{% rbac_menu request %}</div>
        <div class="pd-content">{% block content %}{% endblock %}</div>
    </div>
    <script src="/static/jquery-1.12.4.js"></script>
    <script>
        {% rbac_js %}
    </script>
{% block js %}{% endblock %}
</body>
</html>
layout.html

 

index.html继承模板

{% extends 'layout.html' %}
    {% block content %}
        Welcome : {{ request.session.user_info.nickname }}
    {% endblock %}
index.html

 request.permission_code_list 传到前端显示用户所具有的权限功能按钮

 

报障页面

{% extends 'layout.html' %}
    {% block content %}
        {# 当用户有POST权限方法在他的权限方法列表permission_code_list里时才显示添加 #}
        <div>
            {% if 'POST' in request.permission_code_list %}
                <a href="/trouble.html?md=post">添加</a>
            {% endif %}
        </div>
       <div>
            <table border="1px">
                {% for row in trouble_list %}
                    <tr>
                        <td>{{ row.title }}</td> {# 报障的标题 #}
                        <td>{{ row.status }}</td> {# 报障的状态 数字 #}
                        <td>
                            {% if 'EDIT' in request.permission_code_list %}
                                <a href="/trouble.html?md=edit&nid={{ row.nid }}">编辑</a>
                            {% endif %}
                        </td>
                        <td>
                            {% if 'DEL' in request.permission_code_list %}
                                <a href="/trouble.html?md=del&nid={{ row.nid }}">删除</a>
                            {% endif %}
                        </td>
                        <td>
                            {% if 'DETAIL' in request.permission_code_list %}
                                <a href="/trouble.html?md=detail&nid={{ row.nid }}">查看详细</a>
                            {% endif %}
                        </td>
                    </tr>
                {% endfor %}
            </table>
       </div>
    {% endblock %}
trouble.html

 

后端处理的trouble函数

def trouble(request):
    # 请求方法request.permission_code 是LOOK时
    if request.permission_code == 'LOOK':
        # 获取报障表中登录用户所自己提出的报障列表
        trouble_list = models.Order.objects.filter(create_user_id=request.session['user_info']['nid'])
        return render(request,'trouble.html',{'trouble_list':trouble_list})
    # 请求方法request.permission_code 是DEL时
    elif request.permission_code == 'DEL':
        nid = request.GET.get('nid')  # 获取用户的创建的报障单中某一条的具体的ID,然后进行删除
        models.Order.objects.filter(create_user_id=request.session['user_info']['nid'],nid=nid).delete()
        return redirect('/trouble.html')
    # 想要提交报障单
    elif request.permission_code == 'POST':
        if request.method == 'GET':
            return render(request,'trouble-add.html')  # 给他返回一个填写报障单的页面
        else:
            # 获取填写的标题、内容等,然后写入Order表中
            title = request.POST.get('title')
            content = request.POST.get('content')
            models.Order.objects.create(title=title,detail=content,create_user_id=request.session['user_info']['nid'])
            return redirect('/trouble.html')
    # 想要进行编辑
    elif request.permission_code == 'EDIT':
        if request.method == 'GET':
            # 在数据库中查到要编辑的那条信息,返回给前端渲染出来
            nid = request.GET.get('nid')
            obj = models.Order.objects.filter(create_user_id=request.session['user_info']['nid'],nid=nid).first()
            return render(request,'trouble-edit.html',{'obj':obj,'nid':nid})
        else:
            # url中拿到文章nid 在POST中拿到更改的信息
            nid = request.GET.get('nid')
            new_title = request.POST.get('new_title')
            new_content = request.POST.get('new_content')
            models.Order.objects.filter(create_user_id=request.session['user_info']['nid'],nid=nid).update(title=new_title,detail=new_content)
            return redirect('/trouble.html')
    # 要查看具体的报障信息的话
    elif request.permission_code == 'DETAIL':
        # url中拿到文章nid 查到具体对象 返回前端渲染出来
        nid = request.GET.get('nid')
        obj = models.Order.objects.filter(create_user_id=request.session['user_info']['nid'], nid=nid).first()
        return render(request,'trouble-detail.html',{'obj':obj})
def trouble(request):

 

--------------------------------------------------------------------------------------------------------------------------------------------------

重新再记录一边更详细的过程

一、项目需求分析

  对登录的用户进行权限管理,包括了给用户分配权限( 即用户可以看到自己可以操作的方法和URL链接绑定起来 ),回收权限( 员工离职后要把他的相应权限和个人信息删除掉,保证员工不能干坏事)。

 二、表结构关系

 

 三、计划

  我们打算创建这样一个组件,在settings中的中间件注册一个类,这个类用来做以下内容:

  1. 跳过无需权限访问的URL,我们可以在配置文件中写一个白名单,

# 无需权限控制的URL(白名单)
RBAC_NO_AUTH_URL = [
    '/login.html',
    '/index.html',
    '/register.html',
    '/admin.*',
    '/rbac.*',
]
View Code

  如果当前访问的URL(request.path_info)在白名单中则直接跳过,

import re
from django.conf import settings
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

class RbacMiddleware(MiddlewareMixin):
    def process_request(self, request, *args, **kwargs):
        """
        检查用户是否具有权限访问当前URL
        :param request: 
        :param args: 
        :param kwargs: 
        :return: 
        """
        """跳过无需权限访问的URL"""
        print(request.path_info)
        for pattern in settings.RBAC_NO_AUTH_URL:
            if re.match(pattern, request.path_info):
                return None
rbac.py

  不用检验用户的权限了,因为你要给用户看到网站的主页和登录注册界面啊,要是什么都限制了,那么用户连登录也登录不了了。

  2.获取当前用户session中的权限信息,假设用户是访问登录界面,则会跳过这个中间件,直接到登录界面,用户输入账号和密码后直接POST或者Ajax到后台的login函数验证,login函数根据发过来的用户名和密码去数据库的User表找,找到了,那么就把当前的用户的一些信息写入session中,还有把当前用户的拥有的方法和URL权限也写入session中,或者Form组件验证。

from django.shortcuts import render,HttpResponse,redirect
from django.shortcuts import render,HttpResponse,redirect
from mysite import models
from rbac import models as Rbacmodels
def test(request):
    return HttpResponse('...')

def login(request):
    if request.method == 'GET':
        return render(request,'login.html')
    else:
        u = request.POST.get('username')
        p = request.POST.get('passwd')
        # 跨表到rbac的用户表里拿用户名和密码
        obj = models.UserInfo.objects.filter(user__username=u,user__password=p).first()
        # obj.id 是UserInfo表里的自增id
        # obj.nickname
        # obj.user_id 是rbac的User表里的用户id
        # obj.id和obj.user_id不一样
        if obj:# 表示用户存在,登录成功
             # 获取当前用户权限
             # 获取当前用用户菜单
             # 去配置文件里拿相应的key,写入session中
             # 在rbac组件的service.py中的initial_permission已经把上面的步骤都做好了,只需要传入参数request和obj.user_id
             from rbac.service import initial_permission
             initial_permission(request,obj.user_id)

             request.session['user_info'] = {'username':u,'nickname':obj.nickname,'nid':obj.id} # 添加一些自己的信息

             # return redirect('/index.html')
             return render(request,'index.html',{'obj':obj})
        else:
            return render(request,'login.html')
views.py

  其中把当前用户的拥有的方法和URL权限也写入session中时由于代码比较多于是封装在一个py文件的函数中,只需要传入request和用户ID即可。

  接下来详细讨论一下把权限信息写入session的步骤:

  我们给封装在service.py的initial_permission函数传入了请求信息request和用户的id,首先我们要做的就是初始化权限信息,

    1.根据用户id拿到用户对应的角色(一个用户可以扮演多个角色)

    2.通过 role__in=roles 拿到  URL&方法&角色  表 对应的数据并通过distinct()去重。拿到字典类型 类似这样子{'permission__url':'trouble_kill.html','action__code':'add'}

p2a = models.Permission2Action2Role.objects.filter(role__in=roles).values('permission__url',"action__code").distinct()

    3.创建一个字典 user_permission_dict = {}

    4.遍历 p2a 拿到的多条数据对象,如果字典user_permission_dict 中没有 permission__url ,表明是第一次加入这个URL,对应的把它的具有的action方法加入以列表的形式作为该URL的value值,否则走else的时候就是user_permission_dict中已经有该URL了,但是传来了另一个action方法,比如user_permission_dict字典的形式为 { '/index.html': ['DEL'] } ,第二次传来的是{'permission__url':'/index.html','action__code':'POST'} 相同URL的时候走else然后把新的value值'POST'加入该URL对应的列表中,最后可能变成这样 { '/index.html': ['GET','POST','DEL','EDIT]}  该用户对应拥有的URL所拥有的action方法封装成一个字典,

    for item in p2a:
        if item['permission__url'] not in user_permission_dict:
            user_permission_dict[item['permission__url']] = [item['action__code'], ]
        else:
            user_permission_dict[item['permission__url']].append(item['action__code'])

    5.然后 request.session[settings.RBAC_PERMISSION_SESSION_KEY] = user_permission_dict 把用户的权限写入session中,其中user_permission_dict可能长下面这样:

user_permission_dict={
                    '/index.html': ['GET','POST','DEL','EDIT],
                    '/detail-(\d+).html': ['GET','POST','DEL','EDIT],
                    }
View Code

    6.紧接着我们要初始化菜单信息了,首先把Menu表的 'id', 'caption', 'parent_id' 信息拿到,并转换为列表中包含多个字典的menu_list,通过跨表拿到权限id、权限的URL、权限的名称、权限挂载到的菜单id,外表包一层list列表,里边是一个个字典。

menu_permission_list = list(models.Permission2Action2Role.objects.filter(role__in=roles,
                                                                        permission__menu__isnull=False).values(
        'permission_id',
        'permission__url',
        'permission__caption',
        'permission__menu_id').distinct())
View Code

    7.紧接着我们就可以把菜单列表(传到前端页面显示菜单栏)和菜单权限列表写入session中了。

request.session[settings.RBAC_MENU_PERMISSION_SESSION_KEY] = {
        settings.RBAC_MENU_KEY: menu_list,
        settings.RBAC_MENU_PERMISSION_KEY: menu_permission_list
    }
View Code

       8.此时request.session已经有我们需要的信息大概封装了以下类似信息

user_permission_dict={
                    '/index.html': ['GET','POST','DEL','EDIT],
                    '/detail-(\d+).html': ['GET','POST','DEL','EDIT],
                    }
request.session[settings.RBAC_PERMISSION_SESSION_KEY] = user_permission_dict

menu_list = [
    {'id':1,'caption':'财务查询','parent_id':None},
    {'id':2,'caption':'报障单管理','parent_id':None},
]
menu_permission_list = [
    {'permission_id':1,
     'permission__url':'trouble_kill.html',
     'permission__caption':'提交报障单',
     'permission__menu_id':2},
    {'...'}
]
request.session[settings.RBAC_MENU_PERMISSION_SESSION_KEY] = {
        settings.RBAC_MENU_KEY: menu_list,
        settings.RBAC_MENU_PERMISSION_KEY: menu_permission_list
    }
View Code

       9.详细的service.py代码如下,

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import re
from django.conf import settings
from . import models

def initial_permission(request, user_id):
    """
    初始化权限,获取当前用户权限并添加到session中
    将当前用户权限信息转换为以下格式,并将其添加到Session中
        {
            '/index.html': ['GET','POST','DEL','EDIT],
            '/detail-(\d+).html': ['GET','POST','DEL','EDIT],
        }
    
    :param request: 请求对象
    :param user_id: 当前用户id
    :return: 
    """

    """初始化权限信息"""
    roles = models.Role.objects.filter(users__user_id=user_id)

    p2a = models.Permission2Action2Role.objects.filter(role__in=roles).values('permission__url',
                                                                              "action__code").distinct()
    user_permission_dict = {}
    for item in p2a:
        if item['permission__url'] in user_permission_dict:
            user_permission_dict[item['permission__url']].append(item['action__code'])
        else:
            user_permission_dict[item['permission__url']] = [item['action__code'], ]

    request.session[settings.RBAC_PERMISSION_SESSION_KEY] = user_permission_dict

    """初始化菜单信息,将菜单信息和权限信息添加到session中"""
    menu_list = list(models.Menu.objects.values('id', 'caption', 'parent_id'))

    menu_permission_list = list(models.Permission2Action2Role.objects.filter(role__in=roles,
                                                                        permission__menu__isnull=False).values(
        'permission_id',
        'permission__url',
        'permission__caption',
        'permission__menu_id').distinct())
    request.session[settings.RBAC_MENU_PERMISSION_SESSION_KEY] = {
        settings.RBAC_MENU_KEY: menu_list,
        settings.RBAC_MENU_PERMISSION_KEY: menu_permission_list
    }

def fetch_permission_code(request, url):
    """
    根据URL获取该URL拥有的权限,如:["GET","POST"]
    :param request: 
    :param url: 
    :return: ["GET","POST"]
    """
    user_permission_dict = request.session.get(settings.RBAC_PERMISSION_SESSION_KEY)
    if not user_permission_dict:
        return []
    for pattern, code_list in user_permission_dict.items():
        if re.match(pattern, url):
            return code_list
    return []
service.py

   如果request.session.get(settings.RBAC_PERMISSION_SESSION_KEY) 拿不到权限信息,则直接返回无权限访问的信息,如果拿到了,那么请看下面的第三步。

  3.当前URL和session中的权限进行匹配。

flag = False
        for pattern, code_list in permission_dict.items():
            upper_code_list = [item.upper() for item in code_list]  # 把方法列表都变成大写  ['GET','POST','DEL','EDIT]
            if re.match(pattern, request.path_info):                # 匹配可以访问的url和当前URL
                # settings.RBAC_QUERY_KEY是'md' ; 异常时默认拿到settings.RBAC_DEFAULT_QUERY_VALUE 即'GET'
                request_permission_code = request.GET.get(settings.RBAC_QUERY_KEY, settings.RBAC_DEFAULT_QUERY_VALUE).upper()
                if request_permission_code in upper_code_list:
                    request.permission_code = request_permission_code  # 当前的方法权限加入request
                    request.permission_code_list = upper_code_list     # 当前的方法权限列表加入request中
                    flag = True
                    break
View Code

    1. 我们遍历写在session中的权限信息,数据类型可能是这样的。

permission_dict={
       '/index.html': ['get','post','del','edit'],
       '/detail-(\d+).html': ['get','post','del','edit],
}

    2. 把URL赋值给 pattern,把方法列表赋值给 code_list ,

    3. upper_code_list = [item.upper() for item in code_list] # 把方法列表都变成大写 ['GET','POST','DEL','EDIT]

    4. 然后拿到当前的URL :request.path_info 通过正则匹配当前pattern值对应的URL看当前请求的url 和权限列表中是否匹配,不匹配则接着for循环找,匹配的话走5

    5. # settings.RBAC_QUERY_KEY是'md' ; 异常时默认拿到settings.RBAC_DEFAULT_QUERY_VALUE 即'GET' , request.GET.get() 拿到如URL中 md = ‘del’ 等的方法,出错则默认拿到 'GET' 方法。

request_permission_code = request.GET.get(settings.RBAC_QUERY_KEY, settings.RBAC_DEFAULT_QUERY_VALUE).upper()

    6.如果检测到当前URL中md等于的某个方法在code_list中时,把request.permission_code = request_permission_code # 当前的方法权限加入request

    7. request.permission_code_list = upper_code_list # 当前的方法权限列表加入request中 ,然后结束循环。

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import re
from django.conf import settings
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

class RbacMiddleware(MiddlewareMixin):
    def process_request(self, request, *args, **kwargs):
        """
        检查用户是否具有权限访问当前URL
        :param request: 
        :param args: 
        :param kwargs: 
        :return: 
        """
        """跳过无需权限访问的URL"""
        print(request.path_info)
        for pattern in settings.RBAC_NO_AUTH_URL:
            if re.match(pattern, request.path_info):
                print(request.path_info,pattern)
                return None

        """获取当前用户session中的权限信息"""
        permission_dict = request.session.get(settings.RBAC_PERMISSION_SESSION_KEY)
        if not permission_dict:
            # settings.RBAC_PERMISSION_MSG 返回错误信息:'无权限访问'
            return HttpResponse(settings.RBAC_PERMISSION_MSG)

        """当前URL和session中的权限进行匹配"""

        flag = False
        for pattern, code_list in permission_dict.items():
            upper_code_list = [item.upper() for item in code_list]  # 把方法列表都变成大写
            if re.match(pattern, request.path_info):                # 匹配可以访问的url和当前URL
                # settings.RBAC_QUERY_KEY是'md' ; 异常时默认拿到settings.RBAC_DEFAULT_QUERY_VALUE 即'GET'
                request_permission_code = request.GET.get(settings.RBAC_QUERY_KEY, settings.RBAC_DEFAULT_QUERY_VALUE).upper()
                if request_permission_code in upper_code_list:
                    request.permission_code = request_permission_code  # 当前的方法权限加入request
                    request.permission_code_list = upper_code_list     # 当前的方法权限列表加入request中
                    flag = True
                    break

        if not flag:
            # settings.RBAC_PERMISSION_MSG 返回错误信息:'无权限访问'
            return HttpResponse(settings.RBAC_PERMISSION_MSG)
rbac.py

   4.以上流程过后,那么证明了你是合法的用户和请求,那么你就可借接着跳转到你的页面了,做一些你可以被允许做的事情:

def index(request):
    # permission_code是在中间件的代码里获取的当前登录用户所请求的权限方法
    # request.permission_code 当前登录用户所请求的权限
    # request.permission_code_list 当前登录用户所具有的权限方法
    if not request.session.get('user_info'):
        return redirect('/login.html')

    return render(request,'index.html')
    # if request.permission_code == 'GET':
    #     # 查看权限
    #     pass
    # elif request.permission_code == 'POST':
    #     # 增加权限
    #     pass
    # elif request.permission_code == 'DEL':
    #     # 删除权限
    #     pass
    # elif request.permission_code == 'EDIT':
    #     # 编辑权限
    #     pass
    # return render(request,'index.html')
views.py

 

  待更新......

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/guotianbao/p/7685544.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值