Django_rbac_demo 权限控制组件框架模型
rbac 权限控制组件
- 基于角色的权限控制
- 本质每个权限即为一个 URL
项目组件结构
表结构
Role (title, permission) -(ManyToManyField)- User (name, pwd, roles)
|
(ManyToManyField)
|
Permission (title, url)
实际生成表 及 测试数据
Django_rbac/ rbca/models.py
from django.db import models # Create your models here. 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
核心代码部分
Django_rbac/ rbac/service/permission.py
用于获取当前用户的权限信息
""" 为了解耦,将处理权限的代码保存在组件里面 """ def initial_session(user,request): # 查看当前用户的所有的权限 # 因为会有values 的原理会导致有重复需要去重 ret = user.roles.all().values("permissions__url").distinct() permission_list = [] # 将所有的权限保存在一个列表里面,稍微处理下数据便于操作 for i in ret: permission_list.append(i["permissions__url"]) # 把用户的用户权限保存在 session 里面 request.session["permission_list"] = permission_list
Django_rbac/rbac/service/rbca.py
基于当前用户的权限信息对来访请求进行逻辑判断筛选返回结果
为了不冗余代码写在中间件中,对每一次的请求都做计算
因中间件的工作机制导致所有的请求都被计算,需要对特殊的 URL 进行特殊处理
import re from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse, redirect """ 写在中间件里面可以完全避免每次都要重复校验的问题 在请求来的时候进行校验,因此要写在 process_request 方法里面 """ class ValidPermission(MiddlewareMixin): def process_request(self,request): # 当前访问路径 current_path = request.path_info """ 检查是否属于白名单 admin 的内部流程 不允许一上来就访问首页,必须要跳转到 登陆页面 http://127.0.0.1:8000/admin/login/?next=/admin/ 第二次跳转到登录页面的请求如果没有被定义可通过就会被拦截 无法只使用 admin 为过滤选项 不能用 in 单纯的判断,还是要用到正则处理 需要放过所有 admin 开头的 url """ valid_url_list = ["/login/","/reg/","/admin/.*"] for valid_url in valid_url_list: ret = re.match(valid_url,current_path) if ret: # 中间件 return None 表示这个中间件已经执行完毕 return None """ 校验是否登录 对于没有登陆的用户返回报错应该是让他去登陆 """ user_id = request.session.get("user_id") if not user_id: return redirect("/login/") """ 校验权限 在编辑,以及删除页面的时候 url 不是固定的, 会有内含的参数,因此权限列表里面不能仅仅是写死的url 也不能再单纯的用 in 来判断。还是要靠正则来处理 将权限列表里面的权限信息用 正则表达式来保存 然后对访问页面进行验证是否可以通过来处理 """ permission_list = request.session.get("permission_list",[]) flag = False for permission in permission_list: permission = f"^{permission}$" ret = re.match(permission, current_path) if ret: flag = True break if not flag: return HttpResponse("没有访问权限! ") return None
不要忘记注册在 Django_rbac\Django_rbac\settings.py 里面
其他app 引用使用
Django_rbac/app01/views.py
from django.shortcuts import render,HttpResponse import re # Create your views here. from rbac.models import * from rbac.service.perssions import initial_session def users(request): user_list=User.objects.all() return render(request,"users.html",locals()) def add_user(request): permission_list = request.session["permission_list"] return HttpResponse("add user.....") def roles(request): role_list=Role.objects.all() return render(request,"roles.html",locals()) def login(request): if request.method == "POST": user = request.POST.get("user") pwd = request.POST.get("pwd") # 拿到当前用户对象 user = User.objects.filter(name=user, pwd=pwd).first() if user: # 把用户的id 保存在 session 里面 request.session["user_id"] = user.pk # 查询当前用户的所有的权限 initial_session(user,request) return HttpResponse("登录成功!") return render(request, "login.html",locals())
测试页面代码
这个就比较随意了,看个结果而已。
Django_rbac\templates\login.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <h4>登录页面</h4> <form action="" method="post"> {% csrf_token %} 用户名:<input type="text" name="user"> 密码:<input type="password" name="pwd"> <input type="submit"> </form> </body> </html>
Django_rbac\templates\roles.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <h4>角色列表</h4> <ul> {% for role in role_list %} <p>{{ role }}</p> {% endfor %} </ul> </body> </html>
Django_rbac\templates\users.html
1 <!DOCTYPE html> 2 <html lang="zh-CN"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <meta name="viewport" content="width=device-width, initial-scale=1"> 7 </head> 8 <body> 9 10 <h4>用户列表</h4> 11 <ul> 12 {% for user in user_list %} 13 <p>{{ user }}</p> 14 {% endfor %} 15 16 </ul> 17 18 </body> 19 </html>
本文来自博客园,作者:羊驼之歌,转载请注明原文链接:https://www.cnblogs.com/shijieli/p/10169263.html