rbac组件之权限控制简单实现

web开发中权限指的是什么?

web程序是通过 url 的切换来查看不同的页面(功能),所以权限指的其实就是URL,对url控制就是对权限的控制。

权限表结构设计

"""
一个用户可以有多个角色
一个角色可以有多个用户

一个角色可以有多个权限(也可能为空)
一个权限可以分配给多个角色

用户表与角色表是多对多关系
角色表与权限表是多对多关系 """

rbac组件之权限控制简单实现

 

 

 rbac组件之权限控制简单实现

 

 

 rbac组件之权限控制简单实现

 

 

 rbac组件之权限控制简单实现

 

 

 rbac组件之权限控制简单实现

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和白名单两个全局变量)
"""

 

上一篇:【acwing 寒假每日一题(入门组)】day24数独检查


下一篇:Linux 的进程间通信:管道