Django之管理权限

什么是权限:

  谁对什么资源能做什么操作。

管理权限的实现有很多,这里实现一个最简单的管理权限的实现方式:rbac   ( role based access control )

实现的一个基本思路:

  一张user用户表,一张role角色表,一张permission权限表

其中,用户与角色是多对多的关系,角色和权限是多对多的关系

  用户登录后,通过用户可以获取当前登录人的所有权限,并设置session值(request.session["permission_list"] = 值)

  然后设置中间件,在用户登录时,设置一个白名单,如果用户没有登录就去登录,如果登录就直接从session中取出session_list权限列表,正则匹配这个权限列表,如果匹配上,返回None,否则,返回响应没有访问权限。并且用户可以在左侧菜单查看自己的访问权限有哪些。

首先第一步:表单的设计

如果user用户表借助了auth模块,就直接import 这张表

在rbac这个APP中:(将管理权限设为一个独立的app(组件))  models.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):
    title = models.CharField(max_length=32)
    url = models.CharField(max_length=32)

    code=models.CharField(max_length=32,default="list")

    def __str__(self):
        return self.title

 

 

由于是基于Xadmin的,所以我们要借助这个后台管理,所以要将这几张模型表注册

在rbac  app下的Xadmin.py中注册:

from Xadmin.service.Xadmin import site,ModelXadmin
from .models import User
from .models import Role
from .models import Permission

site.register(User)
site.register(Role)



class PermisssionConfig(ModelXadmin):
    list_display = ["id","title","url","code"]

site.register(Permission,PermisssionConfig)

 

设置中间件,并且将权限列表保存在session中

在rbac下创建一个service的package,然后在新建一个.py文件,用于放置中间件的逻辑。

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import redirect,HttpResponse,render
import re

class ValidPermission(MiddlewareMixin):

    def process_request(self,request):

        print("path",request.path)
        current_path=request.path


        white_list=["/login/","/reg/","/index/","/admin/*"]


        for ignore_url in white_list:
            ret=re.search(ignore_url,current_path)
            if ret:
                return None


        # 校验是否登录

        user_id=request.session.get("user_id")
        if not user_id:
            return redirect("/login/")

        # 校验是否拥有相应权限

        permission_list=request.session.get("permission_list")
        print("permission_list",permission_list)

        for permission in permission_list:
            permission="^%s$"%permission
            ret=re.search(permission,current_path)
            if ret:
                return None

        return HttpResponse("没有访问权限!")

 登录成功后,校验通过后,执行取值和给session赋值:(将这个过程封装到一个.py文件中,哪儿需要直接import即可)

def init_session_permission(user,request):


    permissions = user.roles.all().values("permissions__url","permissions__code","permissions__title").distinct()
    print("permissions",permissions)
    permission_list = []
    menu_permission_dict={}
    for permission in permissions:
        permission_list.append(permission.get("permissions__url"))
        if permission.get("permissions__code")=="list":
            menu_permission_dict[permission.get("permissions__title")]=permission.get("permissions__url")

    request.session["permission_list"] = permission_list
    request.session["menu_permission_dict"] = menu_permission_dict

 备注:要对筛选的结果进行去重操作。因为一个用户会有多个role。

在用户左侧菜单展示可访问的页面

左侧展示页面:首先一点,我们可以给用户展示权限中的那些url,增删改查中,改删是有动态参数的,无法展示,而添加页面显得有些多余,所以我们可以将所有的权限路径中属于展示的url过滤出来,然后加入左侧菜单栏中,为了方便快捷,我们可以在这个permission权限表中,增加一个字段,叫code,我们可以将增删改查设置为四类,然后在登录成功,设置session值时,对查这个url进行过滤,单独保存在一个session中,然后我们可以在相应页面中直接取值,即可,大大的方便了展示信息的代码冗余和可复用性。具体的HTML页面中,我们可以设置到一个母版中,然后用户就可以在不同的页面直接通过继承就可以实现左侧菜单栏的效果。

具体的HTML的实现:

<div class="menu">
        <div class="panel panel-danger">
            <div class="panel-heading">Panel heading without title</div>
            <div class="panel-body">
                {% for title,url in request.session.menu_permission_dict.items %}
                <p><a href="{{ url }}">{{ title }}</a></p>
                {% endfor %}

            </div>
        </div>
    </div>

 

posted @ 2019-03-19 16:14  一抹浅笑  阅读(445)  评论(0编辑  收藏  举报