rbac:基于角色的权限访问控制(Role-Based Access Control)。html
rbac的主要流程:给每一个角色赋予不一样的权限,是这个角色的员工都有这个角色的全部权限。一个角色能够有多我的员担任,一个员工能够担任多个角色(好比部门经理、业务员等)。当员工成功登录系统时,系统须要获取这个员工的多有权限,并放到一个列表里面。而后员工在访问每一个权限url时,系统须要进行判断该员工有没有这个权限进行这项操做。如何判断?就是循环这个员工的全部权限,看有没有对应的权限。这里用到了re模块里面的match方法。django
以下代码:session
# 须要先登录,拿到该员工的权限列表并去重
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/")
登录成功以后,判断查看用户操做权限app
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("用户列表") # 有权限
接下来经过中间件来实现这个功能url
再建立一个应用名字叫作rbac(固然也能够放到同一个应用里面),这个应用里面建立一个包service,包里建立一个名字为permission_li.py的文件。spa
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里面code
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', # 加在这里 ]
接下来的问题就是,加上中间件以后,登录页面也没有权限访问了。csrf
咱们添加白名单,登录、注册和admin页面加里便可。htm
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("没有权限")