权限组件之rbac

rbac:基于角色的权限访问控制(Role-Based Access Control)。

rbac的主要流程:给每个角色赋予不同的权限,是这个角色的员工都有这个角色的所有权限。一个角色可以有多个人员担任,一个员工可以担任多个角色(比如部门经理、业务员等)。当员工成功登陆系统时,系统需要获取这个员工的多有权限,并放到一个列表里面。然后员工在访问每个权限url时,系统需要进行判断该员工有没有这个权限进行这项操作。如何判断?就是循环这个员工的所有权限,看有没有对应的权限。这里用到了re模块里面的match方法。

如下代码:

# 需要先登陆,拿到该员工的权限列表并去重
def
login(request): if request.method=="GET": return render(request,"login.html") else: user=request.POST.get("user") pwd=request.POST.get("pwd") user=UserInfo.objects.filter(name=user,pwd=pwd).first() if user: # 验证成功之后做什么? request.session["user_id"]=user.pk # 设置session # 当前登录用户的所有权限, distinct()是去掉重复的权限 permission_info=user.roles.all().values("permissions__url","permissions__title").distinct() temp=[] # 该员工的全部权限url列表 for i in permission_info: temp.append(i["permissions__url"]) request.session["permission_list"]=temp # {"user_id":1,"permission_list":['/users/','/orders/']} return HttpResponse("登录成功!") else: return redirect("/login/")

 登陆成功之后,判断查看用户操作权限

from django.shortcuts import HttpResponse

def users(request):
    # //users/
    current_path = request.path_info  # 拿到访问的路径
    permission_list = request.session.get("permission_list")  # 取session,从session表里面取到这个员工的所有权限 ['/order/', '/users/']
if not permission_list: # 用户没有登陆,取不到权限列表
return HttpResponse("login.html") # /users/edit/3 为什么要用正则,因为/users/edit/3 与/users/edit/(/d+)不能直接匹配 import re flag = False # 加上标志位 for permission_url in permission_list: ret = re.match(permission_url, current_path) # 用正则去匹配具体的路径,成功则返回对象, 否则返回None if ret: # 如果返回对象 flag = True break if not flag: return HttpResponse("没有访问权限") return HttpResponse("用户列表") # 有权限

 接下来通过中间件来实现这个功能

再创建一个应用名字叫做rbac(当然也可以放到同一个应用里面),这个应用里面创建一个包service,包里创建一个名字为permission_li.py的文件。

from django.utils.deprecation import MiddlewareMixin

from django.shortcuts import  redirect,HttpResponse,render

class M1(MiddlewareMixin):
    def process_request(self,request):
        # //users/
        current_path = request.path_info  # 拿到访问的路径
        permission_list = request.session.get("permission_list")  # 从session表里面取到这个员工的所有权限 ['/order/', '/users/']
        # /users/edit/3  为什么要用正则,因为/users/edit/3 与/users/edit/(/d+)不能直接匹配
        import re
        flag = False  # 加上标志位
        for permission_url in permission_list:
            ret = re.match(permission_url, current_path)  # 用正则去匹配具体的路径,成功则返回对象, 否则返回None
            if ret:  # 如果返回对象
                flag = True
                break
        if not flag:
            return HttpResponse("没有访问权限")

settings.py里面

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'rbac.service.permission_li.M1',  # 加在这里
]

接下来的问题就是,加上中间件之后,登陆页面也没有权限访问了。

我们添加白名单,登陆、注册和admin页面加里即可。

from django.utils.deprecation import MiddlewareMixin

from django.shortcuts import  redirect,HttpResponse,render

class M1(MiddlewareMixin):
    def process_request(self,request):
        pass

        #/admin/login/?next=/admin/
        current_path = request.path_info

        valid_url_menu=["/login/","/reg/","/admin/.*"]
        import re
        for valid_url in valid_url_menu:
            ret=re.match(valid_url,current_path)
            if ret:
                return None

        permission_list = request.session.get("permission_list")
        if not permission_list:
            return redirect("/login/")
        # /users/edit/3
        import re
        flag = False
        for permission_url in permission_list:
            ret = re.match(permission_url, current_path)
            if ret:
                flag = True
                break
        if not flag:
            return HttpResponse("没有权限")

 

posted @ 2018-06-29 17:17  aaronthon  阅读(286)  评论(0编辑  收藏  举报