1 permission权限控制
1 创建项目
参见nb博客:https://www.cnblogs.com/wupeiqi/articles/9178982.html
1 使用pycharm创建虚拟环境:
2 创建项目:
pip install Django==3.2
django-admin startproject crm_permission .
3 创建两个APP:rbac权限组件、web销售管理系统:
python manage.py startapp rbac
python manage.py startapp web
4 在settings.py配置:
INSTALLED_APPS = [
...
'rbac.apps.RbacConfig',
'web.apps.WebConfig',
]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'crm_permission', # 要连接的数据库,连接前需要创建好
'USER': 'root', # 连接数据库的用户名
'PASSWORD': '', # 连接数据库的密码
'HOST': '127.0.0.1', # 连接主机,默认本级
'PORT': 3306 # 端口 默认3306
}
}
5 roleAPP中models表创建:
models.py
from django.db import models
class Permission(models.Model):
"""权限表"""
title = models.CharField(verbose_name="标题", max_length=32)
url = models.CharField(verbose_name="含正则的URL", max_length=128)
def __str__(self):
return self.title
class Role(models.Model):
"""角色表"""
title = models.CharField(verbose_name="角色名称", max_length=32)
permissions = models.ManyToManyField(verbose_name="拥有的所有权限", to="Permission", blank=True)
def __str__(self):
return self.title
class UserInfo(models.Model):
"""用户表"""
name = models.CharField(verbose_name="用户名", max_length=32)
password = models.CharField(verbose_name="密码", max_length=64)
email = models.CharField(verbose_name="邮箱", max_length=32)
roles = models.ManyToManyField(verbose_name="拥有的所有角色", to="Role", blank=True)
def __str__(self):
return self.name
6 webAPP代码呈现
2 权限代码编写
以上简易版客户管理系统中的URL有:
客户管理
客户列表:/customer/list/
添加客户:/customer/add/
删除客户:/customer/list/(?P
修改客户:/customer/edit/(?P
批量导入:/customer/import/
下载模板:/customer/tpl/
账单管理
账单列表:/payment/list/
添加账单:/payment/add/
删除账单:/payment/del/(?P
修改账单:/payment/edit/<?P
那么接下来,我们就在权限组件中录入相关信息:
- 录入权限
- 创建用户
- 创建角色
- 用户分配角色
- 角色分配权限
2-1 基于admin录入信息
python manage.py createsuperuser # 创建超级用户
在rbacAPP下admin.py文件下配置:
from django.contrib import admin
from . import models
admin.site.register(models.Permission)
admin.site.register(models.Role)
admin.site.register(models.UserInfo)
权限的录入:
角色的权限录入:
用户的角色录入:
已录入权限信息的代码下载
3 快速完成基本权限控制
快速实现简单的权限控制的设计思路:
第一次请求:用户输入用户名密码提交---->中间件---->视图---->在到数据库检验数据是否合法,如果成功,从数据库中拿到当前用户的所有权限并放入到session中
第二次请求:用户访问---->中间件判断当前用户访问的url在不在自己的session中---->成功后进入视图
3-1 用户登录
POST请求,用户登录是否合法。获取当前用户的所有权限放入session
login.html
<h3>用户登录</h3>
<form action="" method="post">
{% csrf_token %}
<input type="text" name="user">
<input type="password" name="pwd">
<input type="submit" value="提交"><span style="color: red">{{ msg }}</span>
</form>
urls.py
from django.urls import re_path
urlpatterns = [
...
re_path(r'^login/', account.login),
]
account.py
from django.shortcuts import render, HttpResponse, redirect
from rbac import models
def login(request):
if request.method == "GET":
return render(request, "login.html")
user = request.POST.get("user")
pwd = request.POST.get("pwd")
current_user = models.UserInfo.objects.filter(name=user, password=pwd).first()
if not current_user:
return render(request, "login.html", {"msg": "用户名密码错误"})
# 根据当前用户信息获取此用户拥有的所有权限
permission_queryset = current_user.roles.filter(permissions__isnull=False).values(
"permissions__id",
"permissions__url").distinct()
# 获取权限中所有的url,写入session
permissions_list = [item["permission__url"] for item in permission_queryset]
request.session["crm_permission_url_list"] = permissions_list
return redirect("/customer/list/")
4 权限校验
简易版的权限控制:
xxx.py
import re
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
class CheckPermission(MiddlewareMixin):
"""用户权限信息的校验"""
def process_request(self, request):
# 获取当前用户请求的url
# http://127.0.0.1:8000/customer/list/ ----> /customer/list/
# http://127.0.0.1:8000/customer/list/?age=19 ----> /customer/list/
current_url = request.path_info
# 是否存在于白名单中
valid_url_list = ["/login/", "/admin/.*", ]
for valid_url in valid_url_list:
if re.match(valid_url, current_url):
return None # 执行后续函数
# 获取当前用户在session中保存的权限列表
permission_list = request.session.get("crm_permission_url_list")
if not permission_list:
return HttpResponse("未获取到用户权限信息,请登录!")
# 权限信息的匹配
flag = False
for url in permission_list:
reg = "^{}$".format(url)
if re.match(reg, current_url):
flag = True
break
if not flag:
return HttpResponse("无权访问!")
优化版:含用户登录的源码下载