##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')
##中间件功能:登陆权限验证、黑白名单、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,然后添加到一个列表套字典形式的变量中,渲染给前端来使用该变量