RBAC权限管理

Django中RBAC的应用

什么是权限

说到权限管理,首先要了解,在网站中权限到底是什么?

在网站中,用户通过URL地址,进入网站的后端逻辑,从而对网站的数据库进行操作管理。如果想要让拥有操作管理权限的用户来完成,而没有权限的用户无法操作.

什么是RBAC

RBAC是基于角色的访问控制(Role-Based Access Control )在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便

RBAC介绍

RBAC认为授权实际上是WhoWhatHow 三元组之间的关系,也就是WhoWhat 进行How 的操作,也就是“主体”对“客体”的操作。

Who:是权限的拥有者或主体(如:User,Role)。

What:是操作或对象(operation,object)。

How:具体的权限(Privilege,正向授权与负向授权)。

RBAC生命周期

1、用户登陆验证

2、根据用户身份验证信息,获取用户的角色

3、通过用户所绑定的角色,获取这个角色绑定的所有权限,并去重

4、查询用户所访问的URL是否在角色的权限内,如果在,则继续访问,如果不在,拒绝访问

Django中应用RBAC

1、models.py

from django.db import models


class Permission(models.Model):
    """
    用户的权限
    """
    url = models.CharField(max_length=60)
    title = models.CharField(max_length=30)

    class Meta:
        verbose_name = '权限表'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.title


class Role(models.Model):
    """
    角色表
    """
    name = models.CharField(max_length=30)
    permission = models.ManyToManyField(to='Permission', blank=True, null=True)

    class Meta:
        verbose_name = '角色表'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name

    
class User(models.Model):
    name = models.CharField(max_length=32)
    passwd = models.CharField(max_length=64)
    role = models.ManyToManyField(to='Role')

    class Meta:
        verbose_name = '用户表'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name

2、数据库迁移与执行

python manage.py makemigrations
python manage.py migrate

3、views.py

from django.views import View
from django.http import HttpResponse

from .models import *

# Create your views here.

class LoginView(View):

    def post(self, request):
        # 获取网页提交数据
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 通过网页提交数据,获取数据库中用户对象
        user = User.objects.filter(name=username, passwd=password).first()
        # 判断用户是否存在
        if user:  # 如果用户存在,存入权限列表,存入用户的id
            # 通过获取到的用户对象,获取用户的权限列表
            permissions = user.role.all().values("permission__url")
            # 用列表推导式获取[{'permission__url': '/users/'}] 的value
            permission_list = [item['permission__url'] for item in permissions]
            # 把permission_list存入session中
            request.session["permission_list"] = permission_list
            # 把用户id存入session中
            request.session['user_id'] = user.pk
           
            return HttpResponse('登陆成功')
        else:
            return HttpResponse('登陆失败')

4、中间件方法来添加权限验证

django中间件:在django中,在进入视图函数之前,会先经过中间件,如果想在执行views之前或者之后做一些操作,可以使用django的中间件来完成

在app目录下添加middleware.py文件,写入以下内容

from django.shortcuts import redirect
from django.utils.deprecation import MiddlewareMixin
from django.http import HttpResponse


class ValidPermission(MiddlewareMixin):
    """
    权限验证中间件
    """

    def process_request(self, request):
        # 当前访问路径
        current_path = request.path_info
        print(current_path)
        # 检查是否属于白名单
        valid_url_list=["/app01/login/","/reg/","/admin/.*"]
        # 如果访问的当前路径在名单中
        if current_path in valid_url_list:
            return None

        # 校验是否登录
        user_id=request.session.get("user_id")
        if not user_id:
            return redirect("/login/")

        #  校验权限
        permission_list = request.session.get("permission_list",[])   
        
        if current_path in permission_list:
            return None
        else:
            return HttpResponse("没有访问权限!")

中间件可以定义五个方法,分别是:(主要的是process_request和process_response)

1、process_request(self,request)

2、process_view(self, request, callback, callback_args, callback_kwargs)

3、process_template_response(self,request,response)

4、process_exception(self, request, exception)

5、process_response(self, request, response)

以上方法返回值可以是None或一个HttpResponse对象,如果是None,则继续按照django定义的规则向后继续执行,如果是HttpResponse对象,则直接将该对象返回给用户

5、在settings.py中添加自定义的中间件方法

MIDDLEWARE = [
    
    'app01.middleware.ValidPermission',  # 自定义中间件
]
原文地址:https://www.cnblogs.com/wangxiaosai/p/14187514.html