权限的设计分析和基本使用
浏览目录
权限介绍
1、什么是权限
权限我们应该不陌生,不一样的人权限不同,我们常说“官大一级压死人”,就是说每一个职位权限不同。我们经常会碰到说必须是管理员才能操作,这就是管理员的一种权限。什么是权限呢?总的来说,在我们项目中,就是一个包含正则表达式的URL就是一个权限。
我们简称为RBAC。(url base access control)。
2、作用
权限的作用,就是生成一个独立的组件,我们想用时都可以用。
权限在Django中的操作
说了这么多也不一定会用,下面我们来看一个在Django框架中的实例。
新建项目
我们新建一个project_rbac项目,再建两个app分别为app01和rbac,app01专门放与项目相关逻辑方面的应用,而rbac专门放与权限相关的。
记得在settings.py中配置新建的项目。
配置app
配置静态文件
STATIC_URL = '/static/' STATICFILES_DIRS=[ os.path.join(BASE_DIR,"static") ]
创建表关系
rbac.models.py
建三个类,五张表
# 用户表 class UserInfo(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
角色表和权限表是多对多的关系(一个角色可以有多个权限,一个权限可以对应多个角色)
用户表和角色表是多对多的关系(一个用户可以有多个角色,一个角色有多个用户)
基于admin录入数据
- 先创建一个超级用户 python3 manage.py createsuperuser - 用户名 root - 密码 123456 - 在admin.py 中 from rbac import models admin.site.register(models.Permission) admin.site.register(models.Role) admin.site.register(models.UserInfo) 这样的话上去的是英文的,如果你想让中文显示就在类中加一个类 class Meta: verbose_name_plural = "权限表" - 当你给关联字段录入数据的时候会有错误提示,那么在类中你的那个关联字段在加一个属性blank = True 可以为空 permissions = models.ManyToManyField(to="Permission",verbose_name="具有的所有权限", blank=True)
登录校验
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>登录</title> {% load static %} <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="{% static "bs/css/bootstrap.css" %}"> <style> .container{ margin-top: 150px; } </style> </head> <body> <div class="container"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <div class="panel panel-primary"> <div class="panel-heading">登录页面</div> <div class="panel-body"> <form action="" method="post"> {% csrf_token %} <div class="form-group"> <label for="user">用户名</label> <input type="text" class="form-control" id="user" name="user" placeholder="请输入用户名"> </div> <div class="form-group"> <label for="pwd">密码</label> <input type="password" class="form-control" id="pwd" name="pwd" placeholder="请输入密码"> </div> <input type="submit" class="btn btn-primary login_btn" value="登录"> </form> </div> </div> </div> </div> </div> <script src="{% static '/js/jquery-3.2.1.min.js' %}"></script> <script src="{% static '/bs/js/bootstrap.js' %}"></script> </body> </html>
在rbac应用下面新建service包,新建perssions.py.
def initial_session(user,request): ## 查询当前登录用户的所有权限 permissions = user.roles.all().values("permissions__url").distinct() # 权限列表去重 permission_list = [] for item in permissions: # 循环取到的所有权限 permission_list.append(item["permissions__url"]) # 将该用户的权限url添加到permission_list列表中 print(permission_list) # 在session中注册权限列表 request.session["permission_list"] = permission_list
views.py视图中
# 登录 def login(request): if request.method == "POST": user = request.POST.get("user") # 取到输入的用户名 pwd = request.POST.get("pwd") # 取到输入的密码 user = UserInfo.objects.filter(name=user, pwd=pwd).first() # 判断该用户是否存在于数据库 if user: # 登录成功 # 在session中注册用户ID request.session["user_id"] = user.pk # 查询当前登录用户的所有角色 # user_list= user.roles.all() #角色列表 <QuerySet [<Role: 保洁>, <Role: 销售>]> # 查询当前登录用户的所有权限 initial_session(user,request) return HttpResponse("登录成功") return render(request, "login.html")
权限校验
在rbac应用下面新建service包,新建rbac.py,作为中间件。
在settings中配置中间件。
rbac.py
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 url in valid_url_list: # 查看是否属于白名单 ret = re.match(url, current_path) # 当前路径与白名单列表做匹配 if ret: # 当前路径属于白名单 return None # 通过这个校验 '''校验是否登录 ''' user_id = request.session.get("user_id") # 取到当前登录用户的id值 if not user_id: # 取不到id,说明没登录,跳转到登录页面,重新登录 return redirect("/login/") '''校验权限''' permission_list = request.session.get("permission_list", []) 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
设置白名单,是指所有人都可以访问的url。登录校验,在访问某一些url时,只有登录才能访问,如果没登录,跳转到登录页面。权限校验,判断当前登录用户有哪些权限,对于没有该权限的用户,是无访问的。