python笔记(Django 基于中间件的权限管理,权限粒度控制)

一、基于中间件的权限管理

  1. 权限,角色表的创建

    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
    
  2. 登录成功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)
    
  3. 中间件做权限认证(正则表达式)

     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
    
  4. 在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中配置

在这里插入图片描述

二、权限粒度控制

  1. 更改数据库结构

    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
    
  2. 登录验证:

    permissions = user.roles.all().values("permissions__url","permissions__group_id","permissions__action").distinct()
    
  3. 构建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']
    				 }
    				 
    		           }
    
  4. 中间件校验权限:

    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("没有访问权限!")
    
  5. 菜单权限

    # 注册菜单权限
    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
    
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值