Python Day 78 Django RBAC 基于角色访问控制

  ##RBAC

RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联。简单地说,一个用户拥有若干角色,一个角色拥有若干权限。这样,就构造成“用户-角色-权限”的授权模型。在这种模型中,用户与角色之间,角色与权限之间都是多对多的关系。


#注意:
django在查找模板和静态文件的时候 如果全局没有不会直接报错而是去每一个应用下找templates以及static文件夹 所以能正常引入,这就是django基于应用开发的好处

  ##基于角色访问控制案例如下

  ##在app01应用中创建三张模型表

from django.db import models

# Create your models here.

class User(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)
    roles = models.ManyToManyField(to='Role')

    def __str__(self):
        return self.username
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=255)
    def __str__(self):
        return self.title

  ##引入已经配置好的stark组件完成RBAC,该stark组件功能类似于django自带默认的admin功能

  ##在settings中配置stark应用

  ##在app01应用中创建stark.py文件,然后注册模型表

from stark.service.stark import site,ModelStark
from app01 import models


site.register(models.User)
site.register(models.Role)
site.register(models.Permission)

  ##登录功能

#login.html
{% extends 'stark/base.html' %}


{% block content %}
    <form action="" method="post">
    <h2 class="text-center">登录</h2>
    {% csrf_token %}
    <p>username:<input type="text" class="form-control" name="username"></p>
    <p>password:<input type="password" class="form-control" name="password"></p>
        <input type="submit" class="btn btn-info pull-right">
    </form>
{% endblock %}

#后端
def login(request):

    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        user_obj = models.User.objects.filter(username=username,password=password).first()
        if user_obj:
            #记录当前用户状态
            request.session['username'] = user_obj.username
            #获取当前用户访问权限,还要去重
            permission_list = user_obj.roles.values('permissions__url').distinct()
            # print(permission_list) #<QuerySet [{'permissions__url': '/stark/app01/user/'}, {'permissions__url': '/stark/app01/role/'}]>
            #将当前访问的用户保存到session中
            request.session['permission_list'] = [permission.get('permissions__url') for permission in permission_list]
            return render(request,'index.html',locals())
    return render(request,'login.html')
View Code

  ##中间件功能:登陆权限验证、黑白名单、url访问权限控制

#setting中中间件配置
MIDDLEWARE = [
       'app01.permission.permission.MyPermission',
]

  ###配置中间件 C:CRMapp01permissionpermission.py

import re

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


class MyPermission(MiddlewareMixin):
    def process_request(self,request):
        #获取当前用户像访问的url
        # print(request.path) #获取url后缀
        # print(request.get_full_path()) #获取后缀加get请求参数
        current_path = request.path

        #定义网站白名单,还有给以admin打头的全部通过'/admin/.*'
        white_list = ['/login/','/register/','/index/','/admin/.*']
        # if current_path in white_list:
        #     return None  #判断不太完美 有正则还是要通过正则来匹配
        for url in white_list:
            res = re.search(url,current_path)
            if res:
                return None

        #校验用户是否登录
        if not request.session.get('username'):
            return redirect('/login')

        #校验用户权限
        permission_list = request.session.get('permission_list')
        #判断当前url是否在授权访问的url范围内
        """
            需要考虑的点:url中存在正则匹配,所以要比对存不存在,必须要通过正则来判断存不存在
            不能直接通过in来判断
        """
        for permission in permission_list:
            #固定授权的url,超过该url长度的不能通过匹配
            """
             如:只能查看 http://127.0.0.1:8000/stark/app01/user/
                  每个他授权添加的话就不能匹配到添加url:
                    http://127.0.0.1:8000/stark/app01/user/add/
            """
            permission = '^%s$'%permission
            res = re.search(permission,current_path)
            if res :
                return None
        return HttpResponse('没有权限')

  ##需求:给侧边栏展示用户的所有权限(一般只展示查询,编辑和添加没有意义)

问题:怎么解决哪一个url是查询url,哪一个是编辑或者添加的url
解决方案:通过给权限便permission添加一个flag字段来进行标识,查询url就标识list查询,添加就表示add,编辑就表示edit,删除就用delete来表示
        后端通过获取这个字段来查询哪些是查询url,然后添加到一个列表套字典形式的变量中,渲染给前端来使用该变量
原文地址:https://www.cnblogs.com/liangzhenghong/p/11329512.html