权限

根据URL进行限制用户可以访问的资源

项目与应用的关系

项目可包含多个应用
应用可包含在多个项目中
RBAC:基于权限的管理系统

项目

先创建一个Django项目

Model

from django.db import models


class UserInfo(models.Model):
    name = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32,default=123)
    email = models.EmailField()
    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):
    url = models.CharField(max_length=32)
    title = models.CharField(max_length=32)

    def __str__(self):
        return self.title

 

前端模板

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
</head>
<body>
<form action="/login/" method="post">
    {% csrf_token %}
    <p>用户名<input type="text" name="user"></p>
    <p>密码<input type="password" name="pwd"></p>
    <p><input type="submit"  value="登录"></p>

</form>
</body>
</html>

URL

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
    url(r'^users/', views.user_list),
    url(r'^orders/', views.role_list),
]

 

后端

from django.shortcuts import render, HttpResponse, redirect
from rbac.models import UserInfo, Role, Permission


def login(request):
    if request.method == "GET":
        return render(request, "login.html")
    if request.method == "POST":
        username = request.POST.get("user")
        pwd = request.POST.get("pwd")
        user = UserInfo.objects.filter(name=username, pwd=pwd).first()
        if user:
            request.session["user_id"] = user.pk
            permission_list = user.roles.all().values("permissions__url", "permissions__title").distinct()
            temp = []
            for per_url in permission_list:
                temp.append(per_url["permissions__url"])
            request.session["permissions_list"] = temp
            print(temp)
            return HttpResponse("OK")
        else:
            return redirect('/login/')


def user_list(request):
    return HttpResponse("用户列表")


def role_list(request):
    return HttpResponse("订单列表")

后端有很多的视图函数,如果编写装饰器进行判断用户是否有权限访问,有三十个视图函数,就需要在三十个视图函数上添加装饰器函数,因此装饰器的方法不太妥当,取而代之的是中间件的方法

from django.utils.deprecation import MiddlewareMixin  #注意
from django.shortcuts import render,redirect, HttpResponse
from rbac.models import UserInfo
import re  #注意

class M1(MiddlewareMixin):
    def process_request(self,request):
        current_path = request.path_info
        permission_list = request.session.get("permissions_list")
        print(permission_list)
        valid_menu = ["/login/","/reg/","/admin/.*"]  # 如果不设置白名单,admin的url也会被判为无权限,而且不需要验证的函数少, 先设置白名单,
                                        # 如果用户输入的url在白名单中就会return None
        for valid_url  in valid_menu:
            ret = re.match(valid_url,current_path)   #注意
            if ret:
                return None
        if not permission_list:
            return None
        Flage = False
        for per_url in permission_list:
            re_macth = re.match(per_url,current_path)
            if re_macth:
                Flage = True
                break
        if not Flage:
            return HttpResponse("无权限")

再次解耦后端

在rabc应用之service包intiale 模块中创建一个inital_session函数,登录后处理session

from rbac.service.initial import inital_session

def login(request):
    if request.method == "GET":
        return render(request, "login.html")
    if request.method == "POST":
        username = request.POST.get("user")
        pwd = request.POST.get("pwd")
        user = UserInfo.objects.filter(name=username, pwd=pwd).first()
        if user:
            inital_session(request,user)
            return HttpResponse("OK")
        else:
            return redirect('/login/')
url_filter  模块下的代码
def inital_session(request,user):
    request.session["user_id"] = user.pk
    permission_list = user.roles.all().values("permissions__url", "permissions__title").distinct()
    temp = []
    for per_url in permission_list:
        temp.append(per_url["permissions__url"])
    request.session["permissions_list"] = temp

目录结构如下图

Django——权限组件(中间件判断用户权限--URL初级)

 

创建中间价的步骤

  1、在项目中创建一个应用application,自己命名至于为什么?这是前面提到的:“一个应用可以包含在多个项目中”,方便以后的使用

  2、在项目中创建一个文件夹service,

  3、在service 中创建一个py文件,存放自己中间件类

  4、创建一个类,必须继承  MiddlewareMixin

  5、该类中必须有一个函数,process_request

  6、在该文件下面创建一个inital_session 的模块,处理登录后,session

做好以上步骤,效果如下图

Django——权限组件(中间件判断用户权限--URL初级)

 上面的介绍如何使用中间件控制用户的访问那个函数,下面介绍,根据用户的角色展示菜单

二级菜单

用户登录成功,在cookie中写入用户的权限

import re


def inital_session(request, user):
    request.session["user_id"] = user.pk
    permission_info = user.roles.all().values(
        "permissions__url",  # 权限url
        "permissions__code",  #
        "permissions__title",
        "permissions__id",
        "permissions__permission_group_id",
        "permissions__parent",
        "permissions__parent_id",
        "permissions__permission_group__menu__caption",
        "permissions__permission_group__menu__id",

    ).distinct()
    print(permission_info)
    # 设置用户权限
    dic = {}
    for per_info in permission_info:
        gid = per_info["permissions__permission_group_id"]
        if gid not in dic:
            dic[gid] = {
                "urls": [per_info["permissions__url"]],
                "codes": [per_info["permissions__code"]]
            }
        else:
            dic[gid]["urls"].append(per_info["permissions__url"])
            dic[gid]["codes"].append(per_info["permissions__code"])
    request.session["permissions_dict"] = dic

    ## 设置用户的菜单
    permission_list = []
    for permission_item in permission_info:
       temp = {
           "id":permission_item["permissions__id"],
           "title":permission_item["permissions__title"],
           "url":permission_item["permissions__url"],
           "pid":permission_item["permissions__parent_id"],
           "menu_name":permission_item["permissions__permission_group__menu__caption"],
           "menu_id":permission_item['permissions__permission_group__menu__id'],
       }
       permission_list.append(temp)

    request.session["permission_list"] = permission_list
View Code

相关文章: