Django的权限管理
一:功能分析:
一个成熟的web应用,对权限的控制、管理是不可少的;对于一个web应用来说是什么权限?
这要从web应用的使用说起,用户在浏览器输入一个url,访问server端,server端返回这个url下对应的资源;
所以 对于用户来说 1个可以访问url 就等于1个权限
为什么某些网站会为广大用户做角色划分呢(比如 普通、会员、黑金、白金)?
因为给用户归类后,便于权限的划分、控制、管理;
所以我们把这种基于角色来做得权限控制,称为RBAC(Role Basic Access Control)
二:权限管理数据库表结构设计:
1, 用户表: 用户表和角色表为多对多关系, 1个用户可以有多个角色, 1个角色可以被多个用户划分;
2, 角色表: 角色和权限也是多对多关系, 一个角色可以有多个权限,以恶搞权限可以划分给多个角色
3,菜单表: 由于在前段引导用户找到自己的权限,并可以设置多级菜单对用户权限进行划分;所以权限表和菜单表是1对多关系;
总结: 一般设计包含层级结构嵌套,且嵌套的层级无法预测的表结构使用自关联;(因为无法预测表结构的深度)
三:权限组件录入数据
1, 新建一个django项目
rbac-基于角色的权限控制
2, 增加一个app应用
3, 什么事rbac??
项目与应用的关系
一个项目包含多个应用
一个应用可以包含在多个项目中
基于角色的权限访问控制(Role-Base Access Control)
生成表
4, rbac --》 models.py
3张表,会生成5张表

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
5,数据库迁移
6,查看表,发现没有自己写的表???
7, settins配置
8,入口文件
9, 再次执行数据迁移命令,查看表
admin添加数据
10,添加数据: admin
11, 创建管理员,用户名,密码
12, 登入admin
13,默认没有我们自己写的app里面的表,需要注册才会现实表
14,第三张表不用加。
15
16,添加用户,会自动pop角色表 pop权限表 ---》 先增加一个权限
17,查看权限表字段,目前只显示1列,设置为两个字段!!
18, 自定义显示的字段
展示列
19,角色关系
四:获取登入用户的所有权限
1,url.py
2,登陆代码
views.py

from django.shortcuts import render, redirect from rbac.models import * # Create your views here. def login(request): if request.method == "GET": return render(request, "login.html") else: user = request.POST.get("username") pwd = request.POST.get("password") user = UserInfo.objects.filter(name=user, pwd=pwd).first() if user: pass else: return redirect("/login/")
html

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> {% csrf_token %} <div> user <input type="text" name="username"> </div> <div> password <input type="text" name="password"> </div> <div> <button>login</button> </div> </form> </body> </html>
3, 登陆成功之后做什么???
session
4,登入成功可以写session值,下次查看别的页面就知道是谁了
pk指的是主键
5,查看django_session表
随机字符串={user_id=3, }通过取当前用户的id--->然后就可以取当前用户的所有信息
获取当前用户的所有权限
6,获取当前用户的所有权限
user.roles.all() 找到用户所有角色
a.假设alex登陆成功后,所有的角色title(销售, 销售经理)
b.查看销售角色对应的所有权限
title user.roles.all().values("title", "permission", "permission__url", "permission__title")
......
7,权限去重
又重复的权限,应该去重!!!(title只是为了查看角色, 接下来不打印title, 数据就完全相同了。)
user.roles.all().values("permissions__url", "permissions__title").distince()
五:登陆用户权限写入到session中
1,登陆admin,将销售的权限改成智能查看订单列表
2,url.py
3, views.py 这样的情况任何人都能访问
思考问题: 怎么给页面加权限???
将登陆用户权限写入到session中
4,将登陆用户权限列表写入到session里面。
session = {"user_id":1, "permission_list": ["/users/", "/orders/"]}
5,访问用户列表,用户订单的时候,取session里面取值(权限列表)
判断条件: 只要访问的url在权限列表里面,则可以访问。
6,那么问题来了, 如果url有正则(\d+),怎么判断呢???
正则匹配
7, match方法
import re ret = re.match("/users/edit/(\d+)", "/users/edi123") print(ret) # re.match方法: 匹配不上返回None
匹配成功的返回值
8,users
orders 订单也一样的判断
中间件
1, 问题: 判断代码写到单独的一个文件中,然后中间件中引入。避免太多的重复
2, 应该继承什么呢?
3,复制引入文件的代码到rbac.py文件中
from django.utils.deprecation import MiddlewareMixin class M1(MiddlewareMixin): def process_request(self, request): print("123")
4,配置session文件。将自定义的中间件文件配置一下
6,将判断权限的逻辑代码剪切到rbac.py文件中

from django.utils.deprecation import MiddlewareMixin from django.shortcuts import render, redirect, HttpResponse class M1(MiddlewareMixin): def process_request(self, request): current_path = request.path_info valid_url_menu = ["/login/", "/reg/", "/admin/.*"] # 设置的白名单 import re for valid_url in valid_url_menu: ret = re.match(valid_url, current_path) if ret: return None permission_list = request.session.get("permission_list") if not permission_list: return redirect("/login/") flag = False for permission_url in permission_list: ret = re.match(permission_url, current_path) if ret: flag = True break if not flag: return HttpResponse("没有权限")