web开发中权限指的是什么?
web程序是通过 url 的切换来查看不同的页面(功能),所以权限指的其实就是URL,对url控制就是对权限的控制。
权限表结构设计
""" 一个用户可以有多个角色 一个角色可以有多个用户 一个角色可以有多个权限(也可能为空) 一个权限可以分配给多个角色
用户表与角色表是多对多关系
角色表与权限表是多对多关系 """
rbac/models.py
from django.db import models # Create your models here. 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
第一步:
项目例子(无rbac组件,只有业务app,业务app还需自行书写login视图函数和login.html):
链接:https://pan.baidu.com/s/1C3CIfvmcec5y2ChFGIyOBQ
提取码:abab
""" 先创建一个django项目 """
第二步:
""" 创建两个app,一个是业务app,一个是rbac app(权限组件),创建好后去settings.py中对两个app进行注册 """
第三步:
""" 业务app用项目例子代替; rbac权限组件models.py的书写 """ from django.db import models # Create your models here. 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
第四步:
""" rbac权限组件admin.py对models.py中的表进行注册,利用admin后台管理快速添加数据,并建立关系 """ from django.contrib import admin from . import models # Register your models here. admin.site.register(models.Permission) admin.site.register(models.Role) admin.site.register(models.Userinfo)
第五步:
""" 将用户所对应的权限放到session中,每次用户登录的时候session中就有该用户的所有权限,把这一步权限初始化的步骤封装到rbac组件,业务app的登录功能到时直接调用该封装即可完成权限初始化
PERMISSION_SESSION_KEY是在settings.py中设置的全局变量,这样设置的好处是后期需要用到该session的地方可能有很多,如果改动只需要改全局配置即可,方便快捷
PERMISSION_SESSION_KEY="current_permission_url"
角色所对应权限可能为空,所以要做一个过滤条件;角色与角色之间权限会有重复,所以要做一个去重 """ from django.conf import settings def init_permission(current_user, request): permission_queryset = current_user.roles.filter( permissions__isnull=False ).values( "permissions__id", "permissions__url", ).distinct() permission_list = [ item["permissions__url"] for item in permission_queryset ] request.session[settings.PERMISSION_SESSION_KEY] = permission_list
第六步:
""" 对权限进行判断校验,可以利用django的中间件,对请求进行做判断即可;请求过来时,获取到用户session中的权限,然后对用户访问的URL与权限进行判断,如果用户访问的URL在权限中,即可访问,如果用户访问的URL不在权限中,那么阻止其访问即可;中间件中的process_request方法让请求通过返回None,阻止请求返回任意数据(HTML/字符串/重定向...只要不是None)
VALID_URL_LIST是在settings.py中设置的全局变量,VALID_URL_LIST=["/login/", "/admin/.*"],这是一个白名单,当用户访问这些URL时,不需要进行权限判断,直接让其通过,最好理解的就是登录了 """ import re from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse from django.conf import settings class RbacMiddleware(MiddlewareMixin): def process_request(self, request): current_url = request.path_info for valid_url in settings.VALID_URL_LIST: if re.match(valid_url, current_url): return None permission_list = request.session.get(settings.PERMISSION_SESSION_KEY) if not permission_list: return HttpResponse("未获取到用户权限信息,请进行登录...") flag = False for url in permission_list: reg = "^%s$" % url if re.match(reg, current_url): flag = True break if not flag: return HttpResponse("无权访问...")
第七步:
""" 业务app登录功能的书写 """ from django.shortcuts import HttpResponse, render, redirect from rbac import models from rbac.service.init_permission import init_permission 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": "用户名或密码错误"}) init_permission(current_user, request) # 权限初始化 return redirect("/customer/list/")
总结:
""" 此版本的rbac组件,简单来说就两个功能的封装 1 权限初始化(登录调用),将用户权限URL放入到session中 2 中间件对用户访问URL进行判断 models.py中有三张表,一张权限表,一张角色表,一张用户表 权限与角色是多对多关系 角色与用户是多对多关系 直接调用该rbac组件,需要自行完成的步骤 1 组件app的注册 2 组件的中间件注册 3 settings.py全局变量的配置(session key和白名单两个全局变量) """