一、基于中间件的权限管理
-
权限,角色表的创建
class User(models.Model): name=models.CharField(max_length=32) pwd=models.CharField(max_length=32) 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): title=models.CharField(max_length=32) url=models.CharField(max_length=32) def __str__(self):return self.title
-
登录成功session数据采集
sever/perssion.py
def initial_session(user,request): permissions = user.roles.all().values("permissions__url").distinct() # .distinct()去重 permission_list = [] for item in permissions: permission_list.append(item["permissions__url"]) print(permission_list) request.session["permission_list"] = permission_list
views.py
request.session["user_id"]=user.pk initial_session(user,request)
-
中间件做权限认证(正则表达式)
import re from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse,redirect class ValidPermission(MiddlewareMixin): def process_request(self,request): # 当前访问路径 current_path = request.path_info # 检查是否属于白名单 valid_url_list=["/login/","/reg/","/admin/.*"] for valid_url in valid_url_list: ret=re.match(valid_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",[]) # ['/users/', '/users/add', '/users/delete/(\\d+)', 'users/edit/(\\d+)'] flag = False for permission in permission_list: permission = "^%s$" % permission ret = re.match(permission, current_path) if ret: flag = True break if not flag: return HttpResponse("没有访问权限!") return None
-
在setting中放入自己的中间件
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.service.rbac.ValidPermission" ]
小知识:
1、什么时候该给路径加反斜杠:若没有加杠Django会自己加杠给重定向一次,相当于访问了浏览器两次。去除重定向:APPEND_SLASH = False 在setting.py中配置
二、权限粒度控制
-
更改数据库结构
class Permission(models.Model): title=models.CharField(max_length=32) url=models.CharField(max_length=32) action=models.CharField(max_length=32,default="") group=models.ForeignKey("PermissionGroup",default=1) def __str__(self):return self.title class PermissionGroup(models.Model): title = models.CharField(max_length=32) def __str__(self): return self.title
-
登录验证:
permissions = user.roles.all().values("permissions__url","permissions__group_id","permissions__action").distinct()
-
构建permission_dict
原始permission_dict:permissions: [ {'permissions__url': '/users/add/', 'permissions__group_id': 1, 'permissions__action': 'add'}, {'permissions__url': '/roles/', 'permissions__group_id': 2, 'permissions__action': 'list'}, {'permissions__url': '/users/delete/(\\d+)', 'permissions__group_id': 1, 'permissions__action': 'delete'}, {'permissions__url': 'users/edit/(\\d+)', 'permissions__group_id': 1, 'permissions__action': 'edit'} ]
经过的数据处理函数:
permission_dict= {} for i in permissions: id = i.get('permissions__group_id') if id not in permission_dict: permission_dict[id] = { 'urls':[i.get('permissions__url'),], 'action':[i.get('permissions__action'),] } else: permission_dict[id].get('urls').append(i.get('permissions__url')) permission_dict[id].get('action').append(i.get('permissions__action'))
得到最终的数据:
permission_dict = { 1: { 'urls': ['/users/', '/users/add/', '/users/delete/(\\d+)', 'users/edit/(\\d+)'], 'actions': ['list', 'add', 'delete', 'edit'] }, 2: { 'urls': ['/roles/'], 'actions': ['list'] } }
-
中间件校验权限:
permission_dict=request.session.get("permission_dict") for item in permission_dict.values(): urls=item['urls'] for reg in urls: reg="^%s$"%reg ret=re.match(reg,current_path) if ret: print("actions",item['actions']) request.actions=item['actions'] return None return HttpResponse("没有访问权限!")
-
菜单权限
# 注册菜单权限 permissions = user.roles.all().values("permissions__url","permissions__action","permissions__group__title").distinct() print("permissions",permissions) menu_permission_list=[] for item in permissions: if item["permissions__action"]=="list": menu_permission_list.append((item["permissions__url"],item["permissions__group__title"])) print(menu_permission_list) request.session["menu_permission_list"]=menu_permission_list